標籤:dfs sizeof ack sign vector stack 原始碼 lin char
[POI2011]?mieci題目大意:
一個\(n(n\le10^5)\)個點\(m(m\le10^6)\)條邊的無向圖,每條邊有邊權\(0/1\),試找出若干個環,使得每次翻轉環上所有邊的權值,使得最後所有邊權都是\(0\)。
思路:
權值為\(0\)的邊都沒有用,因為若方案存在,一定存在一種方案使得所有環只經過\(1\)邊。
因此我們只留下\(1\)邊,暴力DFS找環即可。注意要加上當前弧最佳化。
原始碼:
#include<stack>#include<cstdio>#include<cctype>#include<vector>#include<cstring>inline int getint() { register char ch; while(!isdigit(ch=getchar())); register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x;}const int N=1e5+1,M=2e6;int deg[N],h[N];bool mark[M],ins[N];struct Edge { int to,next;};Edge e[M];inline void add_edge(const int &u,const int &v) { e[++h[0]]=(Edge){v,h[u]};h[u]=h[0];deg[u]++; e[++h[0]]=(Edge){u,h[v]};h[v]=h[0];deg[v]++;}std::stack<int> stk;std::vector<std::vector<int> > ans;void dfs(const int &x) { if(ins[x]) { const int k=ans.size(); ans.resize(k+1); int y; do { y=stk.top(); stk.pop(); ins[y]=false; ans[k].push_back(y); } while(y!=x); } for(int &i=h[x];~i;i=e[i].next) { const int &y=e[i].to; if(mark[i]) continue; mark[i]=mark[i^1]=true; stk.push(x); ins[x]=true; dfs(y); }}int main() { memset(h,-1,sizeof h); const int n=getint(),m=getint(); for(register int i=0;i<m;i++) { const int u=getint(),v=getint(); if(getint()^getint()) { add_edge(u,v); } } for(register int i=1;i<=n;i++) { if(deg[i]%2==1) { puts("NIE"); return 0; } } for(register int i=1;i<=n;i++) { dfs(i); } printf("%lu\n",ans.size()); for(register unsigned i=0;i<ans.size();i++) { printf("%lu ",ans[i].size()); for(register unsigned j=0;j<ans[i].size();j++) { printf("%d ",ans[i][j]); } printf("%d\n",ans[i][0]); } return 0;}
[POI2011]?mieci