您的位置:首页 > 其它

Timo's mushrooms CSU - 1991 (第十三届湖南省赛热身赛题)

2017-09-05 12:05 183 查看
题目链接:点击打开链接

题目大意:提莫埋了很多蘑菇,有些蘑菇之间有一条有向边,u->v,若u爆炸则v爆炸,而且每个蘑菇只能引起与之相连的一个蘑菇的爆炸(当时题目意思读错,以为是求单向联通分量,然后大错特错~~~~),就是求有向图上的最小路径覆盖,不过因为原图可能存在环,所以要先进行缩点后在跑二分匹配求最小路径覆盖。

//wait...wait...这个是DAG上的最小路径覆盖,所以如果不进行缩点是一定会错的
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=100010;
const int maxm=100010;
struct edge_t
{
int v,next;
}edge[maxm],newedge[maxn];
int Ecnt,newEcnt;
int vertex[maxn],newvertex[maxn];
int Low[maxn],DFN[maxn],Stack[maxn],Belong[maxn];
int Index,top;
int scc;
bool Instack[maxn];
void init_Graph()
{
Ecnt=newEcnt=0;
memset(vertex,-1,sizeof(vertex));
memset(newvertex,-1,sizeof(newvertex));
}
void make_edge(int u,int v)
{
edge[Ecnt].v=v;
edge[Ecnt].next=vertex[u];
vertex[u]=Ecnt++;
}
void make_newedge(int u,int v)
{
newedge[newEcnt].v=v;
newedge[newEcnt].next=newvertex[u];
newvertex[u]=newEcnt++;
}
void Tarjan(int u)
{
int v;
Low[u]=DFN[u]=++Index;
Stack[top++]=u;
Instack[u]=true;
for(int i=vertex[u];i!=-1;i=edge[i].next)
{
v=edge[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]=false;
Belong[v]=scc;
}
while(v!=u);
}
}
void solve(int n)
{
memset(DFN,0,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
Index=scc=top=0;
for(int i=1;i<=n;i++)
if(!DFN[i])
Tarjan(i);
}
int linker[maxn];
bool used[maxn];
bool dfs(int u)
{
for(int i=newvertex[u];i!=-1;i=newedge[i].next)
{
int v=newedge[i].v;
if(!used[v])
{
used[v]=true;
if(linker[v]==-1||dfs(linker[v]))
{
linker[v]=u;
return true;
}
}
}
return false;
}
int hungary()
{
int res=0;
memset(linker,-1,sizeof(linker));
for(int u=1;u<=scc;u++)
{
memset(used,false,sizeof(used));
if(dfs(u)) res++;
}
return res;
}
//缩点建立新图
void Build_newmap(int n)
{
for(int u=1;u<=n;u++)
for(int i=vertex[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(Belong[u]!=Belong[v])
make_newedge(Belong[u],Belong[v]);
}
}
int main()
{
int t;
int n,m;
int u,v;
scanf("%d",&t);
while(t--)
{
init_Graph();

9378
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
make_edge(u,v);
}
solve(n);
Build_newmap(n);
printf("%d\n",scc-hungary());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐