您的位置:首页 > 其它

强连通+最小路径覆盖

2011-08-16 07:58 357 查看
/*

http://acm.hdu.edu.cn/showproblem.php?pid=3861

强连通+最小路径覆盖

*/

#include<iostream>

#include<string>

#include<cstdio>

using namespace std;

int head[5005],n,shead[5005];

int DFN[5005],Low[5005],Stack[5005],Index,top,scc,Belong[5005],ecnt,secnt;

bool Instack[5005],vis[5005];

int link[50005];

struct edge

{

int u,v,next;

}E[1000000],E1[1000000];

void Insert(int u,int v)

{

E[ecnt].u=u;

E[ecnt].v=v;

E[ecnt].next=head[u];

head[u]=ecnt++;

}

void SInsert(int u,int v)//缩完点以后再次构图插边

{

E1[secnt].u=u;

E1[secnt].v=v;

E1[secnt].next=shead[u];

shead[u]=secnt++;

}

bool find(int x)

{

int i,v;

for(i=shead[x];i!=-1;i=E1[i].next)

{

v=E1[i].v;

if(!vis[v])

{

vis[v]=1;

if(link[v]==-1||find(link[v]))

{

link[v]=x;

return 1;

}

}

}

return 0;

}

int MaxMatch()

{

int i,ans=0;

memset(link,-1,sizeof(link));

for(i=1;i<=scc;i++)//注意点是重新构图以后1—scc进行找增广路

{

memset(vis,0,sizeof(vis));

if(find(i))ans++;

}

return ans;

}

void Tarjan(int u)

{

int i,v;

Low[u]=DFN[u]=++Index;

Stack[++top]=u;

Instack[u]=1;

for(i=head[u];i!=-1;i=E[i].next)

{

v=E[i].v;

if(!DFN[v])

{

Tarjan(v);

if(Low[u]>Low[v])

Low[u]=Low[v];

}

else if(Instack[v]&&Low[u]>DFN[v])

Low[u]=DFN[v];

}

if(Low[u]==DFN[u])

{

scc++;

do{

v=Stack[top--];

Instack[v]=0;

Belong[v]=scc;

}while(u!=v);

}

return;

}

void Init()

{

int i,u,v,m;

ecnt=0;

secnt=0;

memset(shead,-1,sizeof(shead));

memset(head,-1,sizeof(head));

scanf("%d%d",&n,&m);

for(i=1;i<=m;i++)

{

scanf("%d%d",&u,&v);

Insert(u,v);

}

}

void Solve()

{

int i,v,u;

scc=top=Index=0;

memset(DFN,0,sizeof(DFN));

memset(Low,0,sizeof(Low));

memset(Instack,0,sizeof(Instack));

for(i=1;i<=n;i++)

{

if(!DFN[i])Tarjan(i);

}

//for(i=1;i<=n;i++)

// printf("~%d ",Belong[i]);

// printf("\n");

for(i=0;i<ecnt;i++)

{

u=E[i].u;

v=E[i].v;

if(Belong[u]!=Belong[v])

{

SInsert(Belong[u],Belong[v]);

//printf("!! %d %d\n",Belong[u],Belong[v]);

}

}

int sum=MaxMatch();

printf("%d\n",scc-sum);

}

int main()

{

int cas;

scanf("%d",&cas);

while(cas--)

{

Init();

Solve();

}

return 0;

}

/*

6

6

1 2

2 3

3 4

4 1

3 6

3 5

8 9

1 2

2 3

3 1

1 4

4 6

1 5

5 6

6 7

5 8

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: