Luogu P3520 [POI2011]SMI-Garbage

题目
把要变边权的边拿出来找Euler回路就行了。正确性显然,因为一条边经过两次相当于对欧拉回路度数的奇偶性没有影响。
然后把一个个小环输出即可,具体的我也不知道怎么输,题目没讲清楚,我按着题解的来的。

#include<cstdio>
#include<cctype>
using namespace std;
namespace IO
{
    char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
    void Put(char x){*oS++=x;if(oS==oT)Flush();}
    int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
    void write(int x,char c){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put(c);}
}
using namespace IO;
const int N=100007,M=1000007;
int n,m,ans[M],num,cnt,head[N],tot=1,ver[M<<1],Next[M<<1],vis[M<<1],deg[N];
void add(int u,int v){ver[++tot]=v,Next[tot]=head[u],head[u]=tot,++deg[u];}
void dfs(int u,int root)
{
    ans[++num]=u,deg[u]-=2;
    for(int i=head[u],v;i;i=Next[i])
    {
	head[u]=i,v=ver[i];
	if(vis[i]) continue;
	vis[i]=vis[i^1]=1;
	if(u^root&&v==root) return (void)(++cnt,ans[++num]=v);
	return dfs(v,root);
    }
}
int main()
{
    n=read(),m=read();
    for(int i=1,u,v,a,b;i<=m;++i)
    {
	u=read(),v=read(),a=read(),b=read();
	if(a^b) add(u,v),add(v,u);
    }
    for(int i=1;i<=n;++i) if(deg[i]&1) return !printf("NIE");
    for(int i=1;i<=n;++i) while(deg[i]) dfs(i,i);
    write(cnt,'\n');
    for(int i=1,j,root,k;i<=num;++i)
    {
	root=ans[i],k=1,++i;
	while(ans[i]^root&&i<=num) ++i,++k;
	write(k,' ');
	for(j=i-k;j<=i;++j) write(ans[j],' ');
	Put('\n');
    }
    return Flush(),0;
}
posted @ 2019-11-25 19:23  Shiina_Mashiro  阅读(118)  评论(0编辑  收藏  举报