计蒜客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,但是不保证AiBiCi互不相同

 

这个题目的主要思想源于混合图求欧拉回路算法

我们考虑一开始让Ai全部连向Bi,这样会有一些点度数不为0

接下来建一张网络流图,由CiBi连边,源点向所有入度比出度大的点连边,

所有出度比入度大的点向汇点连边。

这样每有一个流量流过,就相当于将一条边由“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 }
原文地址:https://www.cnblogs.com/Y-E-T-I/p/7505015.html