hdu 3861 The King’s Problem

来源:互联网 发布:甜品软件 编辑:程序博客网 时间:2024/05/19 16:49

求单侧连通分量的最小个数。

求强连通分量后,在缩点后的图上用二分图匹配找最小路径覆盖即可。

党写的缩点建图,我的匈牙利。。。

#include <stdio.h>#include <stdlib.h>#include <iostream>#include <string.h>#include <stack>using namespace std;const int MAX = 5010;const int MAXM = 500000;struct edge{int to;struct edge *next;void add( int t,struct edge* &b){to=t;next=b;b=this;}};edge a[ MAXM*2 ],*biao[MAX],*fan[MAX],*yu[MAX];int N,M,countt;int TIME,GROUP;int flag[MAX];int label[MAX];int in[ MAX ];stack<int> S;void init( void ){for( int i = 1; i <= N; i++ )biao[i] = fan[i] = yu[i] = NULL,in[i]=0;countt = TIME = GROUP = 0;}void dfs1( int u ) {    flag[u] = 1;        for(edge*p=biao[u];p!=NULL;p=p->next){        if( !flag[p->to] ) dfs1(p->to);    }    S.push( u );} void dfs2( int u ,int group) {    flag[u] = 1;    for(edge*p=fan[u];p!=NULL;p=p->next){        if( !flag[p->to] ) dfs2(p->to,group);    }    label[u] = group;}int total;int mat[MAX];bool used[MAX];int Augment(int x){int i,k;for(edge *p = yu[x]; p != NULL; p = p->next){k = p->to;if( !used[k] ){used[k] = 1;if( mat[k] == -1 || Augment(mat[k]) ){mat[k] = x;return 1;}}}return 0;}int Hungary(int s,int n){memset(mat,-1,sizeof(mat));int i,sum = 0;for(i=s; i<=n; i++){memset(used,0,sizeof(used));if( Augment(i) )sum++;}return sum;}int main(void){int cases,i,j,k,from,to;scanf("%d",&cases);while( cases-- ){scanf("%d%d",&N,&M);init();for( i = 0; i < M; i++ ){scanf("%d%d",&from,&to);a[ countt++ ].add( to, biao[from] );a[ countt++ ].add( from, fan[to] );}memset( flag,0,sizeof(flag) );for( i = 1; i <= N; i++ )if( !flag[i] ) dfs1(i);memset( flag,0,sizeof(flag) );while( !S.empty() ){int u = S.top();S.pop();if( !flag[u] ) dfs2(u,++GROUP);}for( i = 1; i <= N; i++ ){for( edge*p=biao[i]; p!=NULL; p=p->next ){if( label[i] == label[p->to] ) continue;a[countt++].add( label[p->to], yu[ label[i] ] );in[ label[p->to] ]++;}}total = 0;memset( flag,0,sizeof(flag) );total = Hungary(1,GROUP);printf("%d\n",GROUP - total);}return 0;}


原创粉丝点击