03最小路径覆盖问题
可以用天津南开的oj提交,我开始案例都没过,一提交AC,因为是特判。题目链接http://acm.nankai.edu.cn/p2123.html
最小的路径条数=顶点数-最大匹配数。没一条路径就是一条增广路。
我们只需一路递归,只到节点的父亲为-1止,这便是一条路。
这题也可以建图,建立一个超级源点,超级汇点,边权为1.求最大流。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=151; int um,vm,m,tot; int xM[N],yM[N],vis[N],head[N]; struct node { int v,next; }e[N*N]; void add(int a,int b) { e[tot].v=b; e[tot].next=head[a]; head[a]=tot++; } bool find(int u) { for(int i=head[u];i+1;i=e[i].next) { int v=e[i].v; if(!vis[v]) { vis[v]=1; if(yM[v]==-1||find(yM[v]))//增广路 { yM[v]=u; xM[u]=v; return true; } } } return false; } int max_match() { int ret=0; memset(yM,-1,sizeof(yM)); memset(xM,-1,sizeof(yM)); for(int u=1;u<=um;u++) { if(xM[u]==-1) { memset(vis,0,sizeof(vis)); if(find(u)) ret++; } } return ret; } void dfs(int u)//输出路径 { vis[u]=1; if(xM[u]==-1)return ; u=xM[u]; printf(" %d",u); dfs(u); } int main() { int a,b,i; while(scanf("%d%d",&um,&m)!=EOF) { tot=0; memset(head,-1,sizeof(head)); for(i=0;i<m;i++) { scanf("%d%d",&a,&b); add(a,b); } int ret=max_match(); memset(vis,0,sizeof(vis)); for(i=1;i<=um;i++) { if(!vis[i]) { printf("%d",i); dfs(i); printf("\n"); } } printf("%d\n",um-ret); } return 0; }