基准时间限制:1.2 秒 空间限制:262144 KB 分值: 80 难度:5级算法题
给出一个有向图,要求给每条边重定向,使得定向后出度等于入度的点最多,输出答案和任意一种方案
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
题解:奇点不可能入度等于出度,所以最大点数即偶点个数。因为奇点个数为偶数,可以将奇点相连使得都变为偶点,dfs求欧拉回路。
注意:这题卡时间,输出别用printf,用putchar
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int M = 4e5+5; 4 const int N = 1e5+5; 5 vector<int>g[N];//每个点连哪些边 6 vector<int>a;//奇点 7 struct node { 8 int u, v; 9 }e[M];//每条边连哪些点 10 int vis[M];//走欧拉图时标记边状态,1保持不变,2改变方向 11 int du[N];//度数 12 void dfs(int x) { 13 int num = g[x].size(); 14 for(int i = 0; i < num; ++i) { 15 int j = g[x][i]; 16 17 if(vis[j]) continue; 18 19 int u = e[j].u; 20 if(u == x) vis[j] = 1; 21 else vis[j] = 2; 22 23 //printf("%d:%d->%d...%d->%d ",x, u, e[j].v, x, u==x?e[j].v:u); 24 if(u == x) dfs(e[j].v); 25 else dfs(u); 26 } 27 } 28 int main() { 29 int n, m, i, j, u, v; 30 scanf("%d%d", &n, &m); 31 memset(vis, 0, sizeof(vis)); 32 memset(du, 0, sizeof(du)); 33 for(i = 1; i <= m; ++i) { 34 scanf("%d%d", &u, &v); 35 e[i].u = u; 36 e[i].v = v; 37 g[u].push_back(i); 38 g[v].push_back(i); 39 du[u]++; du[v]++; 40 } 41 for(i = 1; i <= n; ++i) if(du[i]&1) a.push_back(i); 42 int num = a.size(); 43 printf("%d ", n - num); 44 45 int t = m; 46 for(i = 0; i < num; i += 2) { 47 e[++t].u = a[i]; 48 e[t].v = a[i+1]; 49 g[a[i]].push_back(t); 50 g[a[i+1]].push_back(t); 51 } 52 //puts(""); 53 for(i = 1; i <= n; ++i) dfs(i); 54 55 for(i = 1; i <= m; ++i) { 56 if(vis[i] == 2) putchar('1'); 57 else putchar('0'); 58 } 59 puts(""); 60 return 0; 61 }