傳送門(mén)
題意:
思路: 一開(kāi)始被題意迷惑了,沒(méi)看出來(lái)差分約束,老菜雞啦。首先看到aj=ai+1a_j=a_i+1aj?=ai?+1可以把aia_iai?分成奇偶,讓后這個(gè)圖就變成一個(gè)二分圖了。再考慮如何連邊:
(1) 對(duì)于b=1b=1b=1的情況,aj=ai+1a_j=a_i+1aj?=ai?+1,轉(zhuǎn)化成不等式就是ai<=aj?1a_i<=a_j-1ai?<=aj??1和aj<=ai+1a_j<=a_i+1aj?<=ai?+1,所以建圖方式為(j,i,?1)(j,i,-1)(j,i,?1)和(i,j,1)(i,j,1)(i,j,1)。
(2) 對(duì)于b=0b=0b=0的情況,∣ai?aj∣=1|a_i-a_j|=1∣ai??aj?∣=1,去掉不等式又可以分成兩種情況:
①①① aj=ai+1a_j=a_i+1aj?=ai?+1 連邊方式跟上面一樣
②②② ai=aj+1a_i=a_j+1ai?=aj?+1,轉(zhuǎn)化成不等式ai<=aj+1a_i<=a_j+1ai?<=aj?+1和aj<=ai?1a_j<=a_i-1aj?<=ai??1,連邊為(j,i,1)(j,i,1)(j,i,1)和(i,j,?1)(i,j,-1)(i,j,?1)。
可以發(fā)現(xiàn)第二種情況有四條邊,即(i,j,1),(i,j,?1),(j,i,1),(j,i,?1)(i,j,1) ,(i,j,-1),(j,i,1),(j,i,-1)(i,j,1),(i,j,?1),(j,i,1),(j,i,?1)。但是對(duì)于(i,j,1)(i,j,1)(i,j,1)轉(zhuǎn)化成不等式j?i<=1j-i<=1j?i<=1,把(i,j,?1)(i,j,-1)(i,j,?1)轉(zhuǎn)成不等式j?i<=?1j-i<=-1j?i<=?1,當(dāng)?shù)谝粋€(gè)成立的時(shí)候,第二個(gè)顯然成立,所以只保留第一個(gè)就行啦。
讓后跑差分約束就好啦,nnn比較小,直接floydfloydfloyd跑順便判斷一下負(fù)環(huán)就好啦。
這里用并查集判斷的二分圖。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=310,mod
=1e9+7,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
,m
;
int g
[N
][N
],p
[N
*2];int find(int x
) { return x
==p
[x
]? x
:p
[x
]=find(p
[x
]); }bool check()
{for(int i
=1;i
<=n
;i
++) if(find(i
)==find(i
+n
)) return true;return false;
}bool floyd()
{for(int k
=1;k
<=n
;k
++)for(int i
=1;i
<=n
;i
++){for(int j
=1;j
<=n
;j
++)g
[i
][j
]=min(g
[i
][j
],g
[i
][k
]+g
[k
][j
]);if(g
[i
][i
]<0) return true;}return false;
}int main()
{
scanf("%d%d",&n
,&m
);for(int i
=1;i
<=n
*2;i
++) p
[i
]=i
;memset(g
,0x3f,sizeof(g
));for(int i
=1;i
<=n
;i
++) g
[i
][i
]=0;for(int i
=1;i
<=m
;i
++){int a
,b
,op
; scanf("%d%d%d",&a
,&b
,&op
);g
[a
][b
]=1; g
[b
][a
]=-1;if(!op
) g
[b
][a
]=1;p
[find(a
)]=find(b
+n
);p
[find(a
+n
)]=find(b
);}if(check()||floyd()) { puts("NO"); return 0; }int ans
=-1,id
=0;for(int i
=1;i
<=n
;i
++){for(int j
=1;j
<=n
;j
++)if(g
[i
][j
]>ans
) ans
=g
[i
][j
],id
=i
;}puts("YES");printf("%d\n",ans
);for(int i
=1;i
<=n
;i
++) printf("%d ",g
[id
][i
]);return 0;
}
總結(jié)
以上是生活随笔為你收集整理的Codeforces Global Round 12 E. Capitalism 差分约束的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。