计蒜客NOIP模拟赛(2)D1T3 深黑幻想
【问题描述】
凡终于发愤图强,决定专心搞OI,不再玩纸牌和坑钱了!没过多久就飘飘然了,总是陷入自己进了集训队的深黑幻想之中。
样听说了之后,决定考一考凡欧拉回路怎么写。
样:“我给你出一道题啊,是欧拉回路的,有N个点……”
凡:“欧拉回路有什么卵用?你看Epacs不会写也能进集训队!”
样:“他不会写欧拉回路,但他会做题啊,比如说这道题……
“有N个点,M条奇怪的单向边,每个边有三个参数Ai,Bi,Ci,你可以指定这条边是从Ai连向Bi还是从Ai连向Ci,要求你构造一种方案使得把这M条边都指定完了之后,每个点的出度和入度相等!”
凡:“这题我会做啊,但是这tmd和欧拉回路有什么关系?!”
【输入格式】
第一行两个正整数N,M,表示点的数目与边的数目
接下来M行,每行三个正整数,代表Ai,Bi,Ci,含义如题目中所示
【输出格式】
输出一个长度为M的由01组成的字符串代表一个合法解
其中第i个位置为0代表Ai向Bi连边,为1代表Ai向Ci连边
如果有多组解,输出任意一组即可,保证存在合法解
【样例输入】
3 2
1 2 3
2 1 3
【样例输出】
00
【数据范围与约定】
测试点编号 |
N,M |
特殊性质1 |
1 |
≤ 10 |
|
2 |
≤ 10 |
|
3 |
≤ 50 |
√ |
4 |
≤ 100 |
√ |
5 |
≤ 1000 |
√ |
6 |
≤ 10000 |
|
7 |
≤ 10000 |
|
8 |
≤ 50000 |
|
9 |
≤ 50000 |
|
10 |
≤ 50000 |
|
特殊性质1: 保证所有的Ci=Bi+1
对于所有数据,保证1<=Ai,Bi,Ci<=N,但是不保证Ai,Bi,Ci互不相同。
这个题目的主要思想源于混合图求欧拉回路算法
我们考虑一开始让Ai全部连向Bi,这样会有一些点度数不为0。
接下来建一张网络流图,由Ci向Bi连边,源点向所有入度比出度大的点连边,
所有出度比入度大的点向汇点连边。
这样每有一个流量流过,就相当于将一条边由“Ai连向Bi”调整为“Ai连向Ci”
最后我们只需要让程序自己去跑网络流检验一下输出方案即可
相信有很多其他的网络流做法可以过掉这道题
%%%%SAC大佬
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 struct Node 9 { 10 int next,to,dis; 11 }edge[500001]; 12 int head[100001],num,cur[100001],dist[100001],n,m,du[100001]; 13 void add(int u,int v,int dis) 14 { 15 edge[num].next=head[u]; 16 edge[num].to=v; 17 edge[num].dis=dis; 18 head[u]=num++; 19 edge[num].next=head[v]; 20 edge[num].to=u; 21 edge[num].dis=0; 22 head[v]=num++; 23 } 24 bool bfs(int S,int T) 25 { 26 int i; 27 memset(dist,-1,sizeof(dist)); 28 queue<int>Q; 29 Q.push(S); 30 dist[S]=1; 31 while (!Q.empty()) 32 { 33 int u=Q.front(); 34 Q.pop(); 35 for (i=head[u];i!=-1;i=edge[i].next) 36 { 37 int v=edge[i].to; 38 if (edge[i].dis>0&&dist[v]==-1) 39 { 40 dist[v]=dist[u]+1; 41 Q.push(v); 42 } 43 } 44 } 45 if (dist[T]==-1) return 0; 46 return 1; 47 } 48 int dfs(int x,int flow,int des) 49 { 50 int res=0; 51 if (flow<=0||x==des) return flow; 52 for (int &i=cur[x];i!=-1;i=edge[i].next) 53 { 54 int v=edge[i].to; 55 if (dist[v]==dist[x]+1&&edge[i].dis) 56 { 57 int tmp=dfs(v,min(flow-res,edge[i].dis),des); 58 if (tmp<=0) continue; 59 edge[i].dis-=tmp; 60 edge[i^1].dis+=tmp; 61 res+=tmp; 62 if (res==flow) return res; 63 } 64 } 65 return res; 66 } 67 int Max_flow() 68 { 69 int ans=0; 70 while (bfs(0,n+1)) 71 { 72 int a=0; 73 memcpy(cur,head,sizeof(cur)); 74 while (a=dfs(0,2e9,n+1)) ans+=a; 75 } 76 return ans; 77 } 78 int main() 79 {int i,a,b,c,tot=0; 80 cin>>n>>m; 81 memset(head,-1,sizeof(head)); 82 for (i=1;i<=m;i++) 83 { 84 scanf("%d%d%d",&a,&b,&c); 85 add(c,b,1); 86 du[b]--;du[a]++; 87 } 88 for (i=1;i<=n;i++) 89 tot+=abs(du[i]); 90 tot/=2; 91 for (i=1;i<=n;i++) 92 { 93 if (du[i]>0) add(0,i,du[i]); 94 else add(i,n+1,-du[i]); 95 } 96 if (Max_flow()==tot) 97 for (i=1;i<=m;i++) 98 printf("%d",edge[i*2-2].dis^1); 99 }