51nod1967路径定向(欧拉回路,带重边的写法)
给出一个有向图,要求给每条边重定向,使得定向后出度等于入度的点最多,输出答案和任意一种方案
Input
第一行两个正整数N,M,表示1-N号点与M条边 接下来M行,每行两个正整数Xi,Yi,表示存在一条有向边从Xi指向Yi N≤10^5, M≤3*10^5, Xi,Yi≤N
Output
第一行一个整数Ans,表示定向后出度等于入度的最大点数 第二行一个长度为M的01字符串,第i位为0表示第i条边不改向,第i位为1表示第i条边改变方向
Input示例
7 7 1 2 2 3 2 3 4 5 1 5 6 7 6 7
Output示例
5 0010110
题解:
这题其实是cf原题,以前做过,博客链接,到现在又不会做了。。。。
不过这题是带有重边的。
那么按照原来欧拉回路的写法是不行的,因为set不能处理重边
这里学到了一个新的写法:
对于边u-v,存在一个边的结构体数组里面,假设这个这个边在数组下标为i
那么g[u].insert(i),g[v].insert(i).
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> #include<stack> #include<set> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define fi first #define se second typedef vector<int> VI; typedef long long ll; typedef pair<int,int> PII; const int inf=0x3fffffff; const ll mod=1000000007; const int maxn=1e5+100; struct edge { int u,v,f; }e[maxn*4]; set<int> g[maxn]; void dfs(int u) { while(g[u].size()) { int i=*g[u].begin(); int v=e[i].u==u? e[i].v:e[i].u; e[i].f=e[i].u==u? 0:1; g[u].erase(i),g[v].erase(i); dfs(v); } } int deg[maxn]; int read() { 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-'0';ch=getchar();} return x*f; } int main() { int n,m; scanf("%d%d",&n,&m); rep(i,1,n+1) g[i].clear(); rep(i,1,m+1) { e[i].u=read(),e[i].v=read(); deg[e[i].u]++,deg[e[i].v]++; e[i].f=0; g[e[i].u].insert(i),g[e[i].v].insert(i); } int cnt=m; int ans=n; rep(i,1,n+1) { if(deg[i]&1) { e[++cnt].u=i,e[cnt].v=n+1,e[cnt].f=0; g[n+1].insert(cnt),g[i].insert(cnt); ans--; } } rep(i,1,n+1) dfs(i); printf("%d\n",ans); rep(i,1,m+1) { if(e[i].f) putchar('1'); else putchar('0'); } puts(""); return 0; }