【PowerOJ1738&网络流24题】最小路径覆盖问题 (最大流)

题意:

 

 思路:

【问题分析】

有向无环图最小路径覆盖,可以转化成二分图最大匹配问题,从而用最大流解决。

【建模方法】

构造二分图,把原图每个顶点i拆分成二分图X,Y集合中的两个顶点Xi和Yi。对于原图中存在的每条边(i,j),在二分图中连接边(Xi,Yj)。然后把二分图最大匹配模型转化为网络流模型,求网络最大流。

最小路径覆盖的条数,就是原图顶点数,减去二分图最大匹配数。沿着匹配边查找,就是一个路径上的点,输出所有路径即可。

【建模分析】

对于一个路径覆盖,有如下性质:

1、每个顶点属于且只属于一个路径。

2、路径上除终点外,从每个顶点出发只有一条边指向路径上的另一顶点。

所以我们可以把每个顶点理解成两个顶点,一个是出发,一个是目标,建立二分图模型。该二分图的任何一个匹配方案,都对应了一个路径覆盖方案。如果匹配数为0,那么显然路径数=顶点数。每增加一

条匹配边,那么路径覆盖数就减少一个,所以路径数=顶点数 - 匹配数。要想使路径数最少,则应最大化匹配数,所以要求二分图的最大匹配。

注意,此建模方法求最小路径覆盖仅适用于有向无环图,如果有环或是无向图,那么有可能求出的一些环覆盖,而不是路径覆盖。

DAG的最小路径覆盖=点数-二分图最大匹配

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef long double ld;
  7 typedef pair<int,int> PII;
  8 typedef pair<ll,ll> Pll;
  9 typedef vector<int> VI;
 10 typedef vector<PII> VII;
 11 //typedef pair<ll,ll>P;
 12 #define N  200010
 13 #define M  200010
 14 #define INF 1e9
 15 #define fi first
 16 #define se second
 17 #define MP make_pair
 18 #define pb push_back
 19 #define pi acos(-1)
 20 #define mem(a,b) memset(a,b,sizeof(a))
 21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 23 #define lowbit(x) x&(-x)
 24 #define Rand (rand()*(1<<16)+rand())
 25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 26 #define ls p<<1
 27 #define rs p<<1|1
 28 
 29 const ll MOD=1e9+7,inv2=(MOD+1)/2;
 30       double eps=1e-6;
 31       int dx[4]={-1,1,0,0};
 32       int dy[4]={0,0,-1,1};
 33 
 34 int head[N],vet[N],len[N],nxt[N],dis[N],num[N][2],vis[N],s,S,T,tot,n,m;
 35 
 36 int read()
 37 {
 38    int v=0,f=1;
 39    char c=getchar();
 40    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 41    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 42    return v*f;
 43 }
 44 
 45 void add(int a,int b,int c)
 46 {
 47     nxt[++tot]=head[a];
 48     vet[tot]=b;
 49     len[tot]=c;
 50     head[a]=tot;
 51 
 52     nxt[++tot]=head[b];
 53     vet[tot]=a;
 54     len[tot]=0;
 55     head[b]=tot;
 56 }
 57 
 58 bool bfs()
 59 {
 60     queue<int>q;
 61     rep(i,1,s) dis[i]=-1;
 62     q.push(S),dis[S]=0;
 63     while(!q.empty())
 64     {
 65         int u=q.front();
 66         q.pop();
 67         int e=head[u];
 68         while(e)
 69         {
 70             int v=vet[e];
 71             if(len[e]>0&&dis[v]==-1)
 72             {
 73                 dis[v]=dis[u]+1;
 74                 q.push(v);
 75             }
 76             e=nxt[e];
 77         }
 78     }
 79     return dis[T]!=-1;
 80 }
 81 
 82 int dfs(int u,int aug)
 83 {
 84     if(u==T) return aug;
 85     int e=head[u],val=0,flow=0;
 86     while(e)
 87     {
 88         int v=vet[e];
 89         if(len[e]>0&&dis[v]==dis[u]+1)
 90         {
 91             int t=dfs(v,min(len[e],aug));
 92             if(!t)
 93             {
 94                 e=nxt[e];
 95                 continue;
 96             }
 97             flow+=t;
 98             aug-=t;
 99             len[e]-=t;
100             len[e^1]+=t;
101             if(!aug) break;
102         }
103         e=nxt[e];
104     }
105     if(!flow) dis[u]=-1;
106     return flow;
107 }
108 
109 void print(int u)
110 {
111     //printf("u=%d\n",u);
112     if(u<=0||u==S) return;
113     printf("%d ",u);
114     int e=head[u];
115     while(e)
116     {
117         int v=vet[e];
118         if(!len[e]&&v<S) print(v-n);
119         e=nxt[e];
120     }
121 }
122 
123 int main()
124 {
125     n=read(),m=read();
126     s=0;
127     rep(i,1,n) num[i][0]=++s;
128     rep(i,1,n) num[i][1]=++s;
129     S=++s; T=++s;
130     rep(i,1,s) head[i]=0;
131     tot=1;
132     while(m--)
133     {
134         int x=read(),y=read();
135         add(num[x][0],num[y][1],1);
136     }
137     rep(i,1,n) add(S,num[i][0],1);
138     rep(i,1,n) add(num[i][1],T,1);
139     int ans=n;
140     while(bfs()) ans-=dfs(S,INF);
141     int e=head[T];
142     while(e)
143     {
144         int v=vet[e];
145         if(len[e])
146         {
147             e=nxt[e];
148             continue;
149         }
150         print(v-n);
151         printf("\n");
152         e=nxt[e];
153     }
154 
155     printf("%d\n",ans);
156     return 0;
157 }

 

posted on 2019-10-26 17:07  myx12345  阅读(205)  评论(0编辑  收藏  举报

导航