bzoj1116[POI2008]CLO*
题意:
n点m边双向图,问能否将一些边变成单向使得每个点只有一个入度。n≤100000,m≤200000。
题解:
结论:当图中每个点都与至少一个环相连时满足条件。故用并查集不断加边,如果两个顶点已在一个集合中,则将该集合根节点打标记,如果不在,若其中一个顶点所在集合被打了标记,则合并后的集合根节点也打标记。最后如果有集合没被打标记说明无法满足条件,否则可以满足。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define inc(i,j,k) for(int i=j;i<=k;i++) 5 #define maxn 100010 6 using namespace std; 7 8 inline int read(){ 9 char ch=getchar(); int f=1,x=0; 10 while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} 11 while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); 12 return f*x; 13 } 14 int n,m,fa[maxn],vis[maxn]; 15 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} 16 int main(){ 17 n=read(); m=read(); inc(i,1,n)fa[i]=i; 18 inc(i,1,m){ 19 int x=find(read()),y=find(read()); 20 if(x==y)vis[x]=1;else{ 21 fa[x]=y; vis[y]|=vis[x]; 22 } 23 } 24 inc(i,1,n)if(!vis[find(i)]){puts("NIE"); return 0;} 25 puts("TAK"); return 0; 26 }
20160831