P3520 [POI2011]SMI-Garbage
Posted 1129-tangqiyuan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3520 [POI2011]SMI-Garbage相关的知识,希望对你有一定的参考价值。
这是一道欧拉回路的板子题,唯一的不同在于要输出是怎么在那几个环上转出的答案,这样就不能用邻接矩阵存图(其实本题的数据也直接否定了邻接矩阵存图的方法)
不断的在寻找一个简单环,并在它上转一次,相当于消掉一个环,并把所有路径记录在一个 stack 之中,在 stack 中一定会形成 这样一种路径 a.....a b......b c.......c因为最后一定会转回起点,所以可以倒序输出一个被同一终点起点包围的点
#include<bits/stdc++.h> using namespace std; int n,m; struct node{ int to,nxt; }e[2000010];int tot; int first[2000010]; int ind[2000010]; stack<int>sta; queue<int>q; int ans; inline void add_edge(int a,int b){ e[++tot].to=b,e[tot].nxt=first[a],first[a]=tot; e[++tot].to=a,e[tot].nxt=first[b],first[b]=tot; } inline int kd(){ int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+(ch^48);ch=getchar();} return x*f; } void dfsl(int x,int root){ ind[x]-=2;//因为正反两边都不能走了所以入度会减二 for(int i=first[x];i;i=e[i].nxt){ int to=e[i].to; if(e[i].to==0)continue; else{ e[i].to=e[((i-1)^1)+1].to=0; //正反两边都不能再走了,就破坏掉 if(to==root){ sta.push(to),sta.push(x); return; } dfsl(to,root); sta.push(x); return; } } } int main(){ n=kd(),m=kd(); for(int i=1;i<=m;i++){ int a=kd(),b=kd(),c=kd(),d=kd(); if(c==d)continue;//只有在不同时才有走这条边的必要 else{ add_edge(a,b); ind[a]++,ind[b]++;//添加边和增加入度 } } for(int i=1;i<=n;i++){ if(ind[i]&1){//如果有奇数入度的边一定是不会有欧拉回路的 cout<<"NIE"<<endl; return 0; } } for(int i=1;i<=n;i++){ if(ind[i]){ while(ind[i]){ dfsl(i,i); ans++; } } } printf("%d ",ans); int root; while(sta.empty()==false){ int now; now=sta.top(); sta.pop(); q.push(now); if(q.size()==1){//如果这是一个开始 root=q.front(); } else if(now==root){//如果陷入轮回,这是一个结束 cout<<q.size()-1<<" "<<now<<" ";q.pop(); while(q.empty()==false)cout<<q.front()<<" ",q.pop();//循环输出在队列里保存好的路径 puts(""); } } return 0; }
以上是关于P3520 [POI2011]SMI-Garbage的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ] 2276: [Poi2011]Temperature