「POI2011 R2 Day1」Garbage【loj】
给定一张 n个点 m条边的无向图,每条边居黑白二色之一,且有一个黑或白的目标颜色。
有一辆卡车,可以从任意一个结点开始,经过一个简单环(不经过重复边或起点以外结点的环)回到出发点,将所有经过边的颜色反转,即黑色变为白色,白色变为黑色。卡车可以从不同的结点出发行走若干次。
请给出一个合法的方案,使得每条边最终都变为目标颜色,或判定不可行。
1.首先,有多个环,所以不用判连通,但是要用并查集确定有多少个连通块
2.因为点数较多,所以用的邻接链表存图k=1(走过这个边,将对应边删除)
3.当前弧优化
#include<bits/stdc++.h> #define re return #define R register #define ll long long #define inc(i,l,r) for(register int i=l;i<=r;++i) const int maxn=100005,maxm=2000005; using namespace std; char buf[1<<21],*p1,*p2; inline int gc(){re p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;} template<typename T>inline void rd(T&x) { char c;bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } int n,m,k=1,cnt=0; int hd[maxn],d[maxn],fa[maxn],vis[maxn]; struct node{ int to,nt; }e[maxm]; inline void add(int x,int y) { e[++k].to=y;e[k].nt=hd[x];hd[x]=k; e[++k].to=x;e[k].nt=hd[y];hd[y]=k; } stack<int>s; inline void dfs(int x) { for(int& i=hd[x];i;i=e[i].nt) { int v=e[i].to; if(v) { e[i].to=e[i^1].to=0; dfs(v); } } s.push(x); ++cnt; } inline int find(int x) { re x==fa[x]?x:fa[x]=find(fa[x]); } int main() { int x,y,a,b; rd(n),rd(m); inc(i,1,n)fa[i]=i; inc(i,1,m) { rd(x),rd(y); rd(a),rd(b); if(a!=b) { add(x,y); ++d[x]; ++d[y]; fa[find(y)]=find(x); } } queue<int>st; inc(i,1,n) if(d[i]%2) {printf("NIE");re 0;} else if(!vis[find(i)]) { st.push(fa[i]);vis[fa[i]]=1; ++cnt; } printf("%d\n",cnt); while(!st.empty()) { cnt=0; dfs(st.front()); st.pop(); printf("%d ",cnt-1); while(!s.empty()) { printf("%d ",s.top()); s.pop(); } printf("\n"); } re 0; }