zoukankan      html  css  js  c++  java
  • [51NOD 1967] 路径定向

    题目传送-51NOD1967

    题意:

    给出一个有向图,要求给每条边重定向,使得定向后出度等于入度的点最多,输出答案和任意一种方案.
    (N≤10^5,M≤3*10^5, Xi,Yi≤N)

    题解:

    考虑
    先当每条边双向。
    如果这个图的所有点的度都是偶数,那么欧拉路径跑一下就行了
    考虑度为奇数的点:连接所有度为奇数的点,使其成为偶数点,显然不会影响正确性
    留个坑。。这个算法的总结。。。

    过程:

    没有过程。。

    代码:

    const int N=100010,M=600010;
    int n,m;
    int head[N],nxt[M<<1],to[M<<1],vis[M<<1],lst=1;
    int cur[N];
    int in[N];
    inline void adde(int x,int y) {
    	nxt[++lst]=head[x]; to[lst]=y; head[x]=lst;
    }
    bool used[N];
    int sta[M<<1],top=0;
    void dfs(int u) {
    	for(int &i=cur[u];i;i=nxt[i])
    		if(!vis[i] && !vis[i^1]) {
    			vis[i]=1;
    			dfs(to[i]);
    			break;
    		}
    }
    inline void Fluery(int S) {
    	sta[++top]=S;
    	while(top) {
    		int u=sta[top--];used[u]=1;
    		bool can=0;
    		for(int &i=cur[u];i;i=nxt[i])
    			if(!vis[i] && !vis[i^1]) {can=1; break;}
    		if(can) dfs(u);
    	}
    }
    
    int seq[N],tot;
    signed main() {
    	read(n); read(m);
    	for(int i=1;i<=m;i++) {
    		int x,y; read(x); read(y);
    		adde(x,y); adde(y,x);
    		++in[x]; ++in[y];
    	}
    	for(int i=1;i<=n;i++)
    		if(in[i]&1) {
    			seq[++tot]=i;
    		}
    	int ans=n-tot;
    	for(int i=1;i<=tot;i+=2) {
    		adde(seq[i],seq[i+1]); adde(seq[i+1],seq[i]);
    	}
    	memcpy(cur,head,sizeof(head));
    	for(int i=1;i<=n;i++)
    		if(!used[i]) Fluery(i);
    	printf("%d
    ",ans);
    	for(int i=1;i<=m;i++) {
    		printf("%d",(vis[i*2] ? 0 : 1));
    	}
    	return 0;
    }
    

    用时:15min(不算学算法)

  • 相关阅读:
    PHP常见问题总结
    Java常见问题总结(二)
    C语言常见问题总结
    C#常见问题总结(三)
    C#常见问题总结(二)
    Android常见问题总结(二)
    日期和时间类函数
    Eclipse开发工具介绍
    JavaScript中逻辑运算符的使用
    多路开关模式的switch语句
  • 原文地址:https://www.cnblogs.com/functionendless/p/9535237.html
Copyright © 2011-2022 走看看