BZOJ3724: PA2014Final Krolestwo

来源:互联网 发布:外星人源码论坛eenot 编辑:程序博客网 时间:2024/06/07 08:40

跪dalao……

我们新建一个点0,连边向所有奇数度点,于是得到了一个偶数条边,所有点度数都是偶数的图
这个图存在欧拉回路,根据每次流出0,流入0的两个奇数点可以配对
但是这题要求路径长度为偶数,于是我们将n个点拆成2n个点,这样配对的奇数点之间的路径长度就是偶数了
我们现在想在2n个点中建入原图中的边,使所有点度数都为偶数
考虑怎么连原图中的边
0的度数显然为偶数
建出原图的生成树,对于不在生成树上的边,在二分图上随便建
然后对于生成树上的边 < fa,x>,
如果x的度数是奇数,连边< x,fa+n>
如果x的度数是偶数,连边< x+n,fa>
这样做能保证x的度数是偶数,因为拆点前x的度数是偶数,所以x+n的度数一定是偶数
于是我们能保证除了树根的两个点root,root+n,所有点的度数都是偶数
因为所有点的度数和是偶数,droot,droot+n一定同奇偶
若他们都为奇数,则存在一条root到root+n的欧拉回路(好吧不能叫回?
因为原图的总边数是偶数,根据二分图性质,从root走完所有边一定在root这边,不合法
所以这种情况不存在
于是所有点度数都是偶数

跑个欧拉回路就好了qaq

code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;inline void read(int &x){    char c; while(!((c=getchar())>='0'&&c<='9'));    x=c-'0';    while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';}const int maxn = 1010000;const int maxm = 2010000;int n,m;int d[maxn],cnt[maxn],e[maxm][2];struct edge{int y,c,nex;}a[maxm]; int len,fir[maxn];inline void ins(const int x,const int y,const int c){    a[++len]=(edge){y,c,fir[x]};fir[x]=len;    a[++len]=(edge){x,c,fir[y]};fir[y]=len;    cnt[x]++,cnt[y]++;}int fa[maxn];int findfa(const int x){return fa[x]==x?x:fa[x]=findfa(fa[x]);}vector<int>V[maxn],vi[maxn];void build(const int x,const int fa,const int fai){    for(int i=0;i<V[x].size();i++) if(V[x][i]!=fa)        build(V[x][i],x,vi[x][i]);    if(x==1) return;    if(cnt[x]&1) ins(x,fa+n,fai);    else ins(x+n,fa,fai);}bool use[maxm];int t[maxm],tp;void dfs(const int x){    for(int k=fir[x];k;k=fir[x])     {        while(k&&use[a[k].c]) k=a[k].nex;        if(!k) return;        use[a[k].c]=true;        fir[x]=a[k].nex;        dfs(a[k].y),t[++tp]=a[k].c;    }}int main(){    read(n); read(m);    for(int i=1;i<=m;i++)    {        int x,y; read(x); read(y);        d[x]++,d[y]++;        e[i][0]=x,e[i][1]=y;    }    for(int i=1;i<=n;i++) if(d[i]&1)        ins(0,i,m+i);    for(int i=1;i<=n;i++) fa[i]=i;    for(int i=1;i<=m;i++)    {        int x=e[i][0],y=e[i][1];        if(findfa(x)==findfa(y)) ins(x,y+n,i);        else        {            fa[findfa(x)]=findfa(y);            V[x].push_back(y),vi[x].push_back(i);            V[y].push_back(x),vi[y].push_back(i);        }    }    build(1,0,0);    dfs(0);    while(tp>0)    {        int ans1,ans2,ans3;        ans1=t[tp--]-m;        int j=tp;while(t[j]<=m) j--;        ans2=t[j]-m;        printf("%d %d %d\n",ans1,ans2,tp-j);        while(tp>j) printf("%d ",t[tp--]); putchar('\n');        tp--;    }    return 0;}
原创粉丝点击