最小路径覆盖问题
Description
给定有向图
G=(V,E)
。
设
P
是
如果
V
中每个顶点恰好在
P
中路径可以从
的路径覆盖。
设计一个有效算法求一个有向无环图
Input
第
1
行有
n
是给定有向无环图
接下来的
m
行,每行有
Output
从第
1
行开始,每行输出一条路径。
文件的最后一行是最少路径数。
Sample Input
11 12
1 2
1 3
1 4
2 5
3 6
4 7
5 8
6 9
7 10
8 11
9 11
10 11
Sample Output
1 4 7 10 11
2 5 8
3 6 9
3
Solution
设
V1={x0,x1,…,xn}∪{y0,y1,…,yn}
,
E1={(x0,xi):i∈V}∪{(yi,y0):i∈V}∪{(xi,yj):(i,j)∈E}
每条边的容量均为
1
。
求网络
Code
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <queue>
- #define Min(x,y) ((x)<(y)?(x):(y))
- using namespace std;
- const int INF=0x3f3f3f3f;
- int m,n,s,t,cnt;
- int low[100000],head[100000],nxt[100000],data[100000];
- int dis[1000];
- bool vis[1000];
- queue<int>q;
- void add(int x,int y,int z){
- nxt[cnt]=head[x];data[cnt]=y;low[cnt]=z;head[x]=cnt++;
- nxt[cnt]=head[y];data[cnt]=x;low[cnt]=0;head[y]=cnt++;
- }
- bool BFS(){
- memset(dis,-1,sizeof dis);
- q.push(s);dis[s]=0;
- while(!q.empty()){
- int now=q.front();q.pop();
- for(int i=head[now];i!=-1;i=nxt[i])
- if(low[i]&&dis[data[i]]<0){dis[data[i]]=dis[now]+1;q.push(data[i]);}
- }
- return dis[t]>0;
- }
- int dfs(int now,int flow){
- if(now==t)return flow;
- int Flow;
- for(int i=head[now];i!=-1;i=nxt[i]){
- if(low[i]&&dis[data[i]]==dis[now]+1){
- if(Flow=dfs(data[i],Min(flow,low[i]))){
- low[i]-=Flow;
- low[i^1]+=Flow;
- return Flow;
- }
- }
- }
- return 0;
- }
- void dfs2(int now){
- vis[now]=true;
- printf(”%d ”,now);
- for(int i=head[now];i!=-1;i=nxt[i]){
- if(!vis[data[i]]&&data[i]!=s&&data[i]!=t&&data[i]>n&&data[i]<=n*2&&!low[i])dfs2(data[i]-n);
- }
- }
- int main(){
- freopen(”path.in”,“r”,stdin);
- freopen(”path.out”,“w”,stdout);
- scanf(”%d%d”,&n,&m);
- memset(head,-1,sizeof head);
- int weight=n;
- s=n+n+1,t=n+n+2;
- for(int i=1;i<=m;i++){
- int x,y;
- scanf(”%d%d”,&x,&y);
- add(x,y+n,1);
- }
- for(int i=1;i<=n;i++){add(s,i,1);add(i+n,t,1);}
- while(BFS()){
- int flag;
- while(flag=dfs(s,INF)){
- weight-=flag;
- }
- }
- for(int i=1;i<=n;i++)if(!vis[i]){
- dfs2(i);
- printf(”\n”);
- }
- printf(”%d\n”,weight);
- return 0;
- }