洛谷1525 關押罪犯(並查集)(黑白染色)
阿新 • • 發佈:2018-12-13
題目
題解1
貪心+擴充套件域並查集 把怨氣值排序,大的當然要分配到兩個不同的監獄。 一個點拆成兩個點,分兩層,不同監獄連不同層。
程式碼
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=20010,maxm=100010; int n,m; int fa[maxn*2]; struct U{int x,y,c;}a[maxm]; bool cmp(U u1,U u2) { return u1.c>u2.c; } int find_fa(int x) { if(x==fa[x]) return x; return find_fa(fa[x]); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n*2;i++) fa[i]=i; for(int i=1;i<=m;i++) { scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].c); } sort(a+1,a+m+1,cmp); for(int i=1;i<=m;i++) { fa[find_fa(a[i].x)]=find_fa(a[i].y+n); fa[find_fa(a[i].x+n)]=find_fa(a[i].y); if(find_fa(a[i].x)==find_fa(a[i].y)) { printf("%d\n",a[i].c); return 0; } } printf("0\n"); return 0; }
題解2
二分+黑白染色 答案顯然滿足二分性,問題轉變成判斷是否存在一種分配方案,使得所有大於mid的怨氣值的人被分在不同監獄。 刪掉所有邊權小於等於mid的邊,然後做黑白染色。如果染色中不發生衝突,那麼這個mid可行。 黑白染色就好像在說,與我連邊(怨氣值大於mid)的人都不能和我有一樣的顏色(監獄)。 這是利用了黑白染色可以判斷是否是二分圖的特點。其原理是判斷是否有奇環,如果一張圖有一個奇環,那麼所有的點都存在與某個奇環。
程式碼
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=20010,maxm=100010; int n,m; struct E{int y,c,next;}e[maxm<<1];int len=0,last[maxn]; void ins(int x,int y,int c) { e[++len]=(E){y,c,last[x]};last[x]=len; } int c[maxn]; bool dfs(int x,int color,int mid) { c[x]=color; for(int k=last[x];k;k=e[k].next) { int y=e[k].y; if(e[k].c<=mid) continue; if(c[y] && c[y]==color) return false; else if(!c[y]) if(!dfs(y,3-color,mid)) return false; } return true; } bool check(int mid) { memset(c,0,sizeof(c)); for(int i=1;i<=n;i++)//debug 列舉所有 if(c[i]==0) if(!dfs(i,1,mid)) return false; return true; } int main() { int mxc=0; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y,c; scanf("%d%d%d",&x,&y,&c); ins(x,y,c);ins(y,x,c); mxc=max(mxc,c); } int l=0,r=mxc,ans; while(l<=r) { int mid=l+r>>1; if(check(mid)) ans=mid,r=mid-1; else l=mid+1; } printf("%d",ans); return 0; }