zoukankan      html  css  js  c++  java
  • 【wikioi】1904 最小路径覆盖问题(最大流+坑人的题+最小路径覆盖)

    http://wikioi.com/problem/1904/

    这题没看数据的话是一个大坑(我已报告官方修复了),答案只要求数量,不用打印路径。。。orz

    最小路径覆盖=n-最大匹配,这个我在说二分图匹配时讲过的。

    但是如果用最大流打印路径怎么办呢?在增广时记录增广路的点之间的链接,然后一个个打印即可。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << #x << " = " << x << endl
    #define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; }
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    
    const int N=5010, M=2000000, oo=~0u>>1, s=5000, t=s+1;
    int ihead[N], cnt=1, d[N], p[N], cur[N], gap[N], n, m, to[N], vis[N];
    struct ED { int from, to, cap, w, next; } e[M];
    inline void add(const int &u, const int &v, const int &c) {
    	e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v; e[cnt].from=u; e[cnt].cap=c;
    	e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].to=u; e[cnt].from=v; e[cnt].cap=0;
    }
    int isap(const int &s, const int &t, const int &nn) {
    	for1(i, 0, t) cur[i]=ihead[i];
    	CC(d, 0); CC(gap, 0);
    	int ret=0, i, f, u=s;
    	gap[0]=nn;
    	while(d[s]<nn) {
    		for(i=cur[u]; i; i=e[i].next) if(e[i].cap && d[u]==d[e[i].to]+1) break;
    		if(i) {
    			p[e[i].to]=cur[u]=i; u=e[i].to;
    			if(u==t) {
    				for(f=oo; u!=s; u=e[p[u]].from) f=min(f, e[p[u]].cap);
    				for(u=t; u!=s;) {
    					int tp=e[p[u]].from;
    					to[tp]=u;
    					if(to[tp]-n>0) vis[tp-n]=1;
    					u=tp;
    				}
    				for(u=t; u!=s; u=e[p[u]].from) e[p[u]].cap-=f, e[p[u]^1].cap+=f;
    				ret+=f;
    			}
    		}
    		else {
    			if(! (--gap[d[u]]) ) break;
    			d[u]=nn; cur[u]=ihead[u];
    			for(i=ihead[u]; i; i=e[i].next) if(e[i].cap && d[u]>d[e[i].to]+1) d[u]=d[e[i].to]+1;
    			++gap[d[u]];
    			if(u!=s) u=e[p[u]].from;
    		}
    	}
    	return ret;
    }
    int main() {
    	read(n); read(m);
    	int u, v;
    	rep(i, m) {
    		read(u); read(v);
    		add(u, v+n, oo);
    	}
    	for1(i, 1, n) add(s, i, 1), add(i+n, t, 1);
    	int ans=n-isap(s, t, t);
    	for1(i, 1, n) {
    		if(vis[i]) continue;
    		print(i);
    		for(u=i; to[u]; u=to[u]-n) printf(" %d", to[u]-n);
    		puts("");
    	}
    	print(ans);
    	return 0;
    }
    

    题目描述 Description

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

    对于给定的给定有向无环图G,编程找出G的一个最小路径覆盖。

    输入描述 Input Description

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

    输出描述 Output Description

    将最小路径覆盖输出。从第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

    数据范围及提示 Data Size & Hint

  • 相关阅读:
    IO 模型
    进程、线程、锁
    用多线程,实现并发,TCP
    同步锁(互斥锁),GIL锁(解释器层面的锁),死锁与递归锁
    Java项目中的常用的异常2
    JAVA项目中的常用的异常处理情况1
    添加学生信息web界面连接数据库
    jdbc下载路径
    添加学生信息 web界面 并且连接数据库
    正则表达式
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3941269.html
Copyright © 2011-2022 走看看