• 网络流24题 最小路径覆盖(DCOJ8002)


    题目描述

    给定有向图 G=(V,E) G = (V, E)G=(V,E)。设 P PP 是 G GG 的一个简单路(顶点不相交)的集合。如果 V VV 中每个顶点恰好在 P PP 的一条路上,则称 P PP 是 G GG 的一个路径覆盖。P PP 中路径可以从 V VV的任何一个顶点开始,长度也是任意的,特别地,可以为 0 00。G GG 的最小路径覆盖是 G GG 的所含路径条数最少的路径覆盖。

    设计一个有效算法求一个有向无环图 G GG 的最小路径覆盖。

    输入格式

    第 1 11 行有 2 22 个正整数 n nn 和 m mm。n nn 是给定有向无环图 G GG 的顶点数,m mm 是 G GG 的边数。
    接下来的 m mm 行,每行有 2 22 个正整数 u uu 和 v vv,表示一条有向边 (i,j) (i, j)(i,j)。

    输出格式

    从第 1 11 行开始,每行输出一条路径。
    文件的最后一行是最少路径数。

    样例

    样例输入

    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

    样例输出

    1 4 7 10 11
    2 5 8
    3 6 9
    3

    数据范围与提示

    1≤n≤200,1≤m≤6000 1 leq n leq 200, 1 leq m leq 60001n200,1m6000

    最小割 最大流

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int maxn=400+10,maxm=6010+maxn;
    int n,m,k,S,T,tot,ans,rb[maxn],rd[maxn];
    bool pl[maxn];int v[maxn];
    
    int aa;char cc;
    int read() {
    	aa=0;cc=getchar();
    	while(cc<'0'||cc>'9') cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	return aa;
    }
    
    struct Node{
    	int x,y,cap,flow;
    }node[2*maxm];
    
    int cur[maxn];
    int fir[maxn],nxt[2*maxm],e=1;
    void add(int x,int y,int z) {
    	node[++e].x=x;node[e].y=y;node[e].cap=z; nxt[e]=fir[x];fir[x]=e;
    	node[++e].x=y;node[e].y=x;node[e].cap=0; nxt[e]=fir[y];fir[y]=e;
    }
    
    int zz[maxn],dis[maxn],s=1,t=0;
    bool BFS() {
    	memset(dis,-1,sizeof(dis));
    	dis[S]=0; s=1,t=0;zz[++t]=S;
    	int x,y;
    	while(s<=t) {
    		x=zz[s];s++;
    		for(y=fir[x];y;y=nxt[y]) {
    			if(node[y].flow>=node[y].cap||dis[node[y].y]!=-1) continue;
    			dis[node[y].y]=dis[x]+1;
    			zz[++t]=node[y].y;
    		}
    	}
    	return dis[T]!=-1;
    }
    
    int DFS(int pos,int maxf) {
    	if(pos==T||!maxf) return maxf;
    	int rs=0,now;
    	for(int &y=cur[pos];y;y=nxt[y]) {
    		if(node[y].flow>=node[y].cap||dis[node[y].y]!=dis[node[y].x]+1) continue;
    		now=DFS(node[y].y,min(maxf,node[y].cap-node[y].flow));
    		node[y].flow+=now;
    		node[y^1].flow-=now;
    		rs+=now;
    		maxf-=now;
    	}
    	if(!rs) dis[pos]=-1;
    	return rs;
    }
    
    int Dinic() {
    	int rs=0;
    	while(BFS()) {
    		memcpy(cur,fir,sizeof(fir));
    		rs+=DFS(S,0x3f3f3f3f);
    	}
    	return rs;
    }
    
    int main() {
    	n=read();m=read();tot=n;
    	int x,y; S=2*n+1;T=S+1;
    	for(int i=1;i<=n;++i) add(S,i,1),add(i+n,T,1);
    	for(int i=1;i<=m;++i) {
    		x=read();y=read();
    		add(x,y+n,1);
    	}
    	ans=tot-Dinic();
    	for(int i=2;i<=e;++i) {
    		if(node[i].x<=n&&node[i].flow==1) {
    			rb[node[i].x]=node[i].y-n;
    			rd[node[i].y-n]=1;
    		}
    	}
    	for(int i=1;i<=n;++i) if(!rd[i]){
    		x=i;printf("%d",i);
    		while(rb[x]) printf(" %d",x=rb[x]);
    		printf("
    ");
    	}
    	printf("%d",ans);
    	return 0;
    }
    

      

    弱者就是会被欺负呀
  • 相关阅读:
    module模块和包(十七)
    swap(十六)
    文件系统
    Confluence 6 管理协同编辑
    Confluence 6 管理协同编辑
    Confluence 6 数据收集隐私策略
    Confluence 6 修改警告的阈值和表现
    Confluence 6 警告的类型
    Confluence 6 诊断
    Confluence 6 垃圾收集性能问题
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/7445410.html
Copyright © 2020-2023  润新知