您的位置:首页 > 其它

HDU 1827 - Summer Holiday(Tarjan + 缩点 + 计算入度)

2016-08-01 21:33 357 查看

题目链接:

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

题解:

与POJ 2553类似,只不过这个是计算入度。

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

vector <int> mapp[5000];
int dfn[5000],low[5000],color[5000],pene[5000],vis[5000],stk[5000],value[5000];
int n,m,x,y,cnt,t,sig;

void init()
{
memset(vis,0,sizeof(vis));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(color,0,sizeof(color));
memset(pene,0,sizeof(pene));
memset(stk, 0, sizeof(stk));
//memset(vist,0,sizeof(vist));
memset(value,0,sizeof(value));
for(int i=1;i<=n;i++)mapp[i].clear();
}

void Tarjan(int u)
{
vis[u] = 1;
low[u] = dfn[u] = cnt++;
stk[++t] = u;
for(int j = 0; j < mapp[u].size(); j++)
{
int v = mapp[u][j];
if(!vis[v]) Tarjan(v);
if(vis[v] == 1)low[u]=min(low[u],low[v]);//这里一定要用if,回溯的关键条件
}
if(dfn[u] == low[u])
{
sig++;
do
{
color[stk[t]]=sig;//缩点之后同一强连通分量的点染成同一种颜色。
vis[stk[t]]=-1;//这个点相当于没了,染成同一种颜色意思就是缩成一个点了
}
while(stk[t--]!=u);
}
}
int fun(int x)//找一张强连通图里最便宜的那个人
{
int minn=INT_MAX;
for(int i=1;i<=n;i++){
if(color[i] == x && value[i]<minn)
minn=value[i];
}
return minn;
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
init();
for(int i = 1; i <= n; i++)
scanf("%d", &value[i]);
for(int i = 1; i <= m; i++)
{
scanf("%d%d", &x, &y);
mapp[x].push_back(y);
}
cnt = 1, t = -1, sig = 0;
for(int i = 1; i <= n; i++)
{
if(!vis[i])
Tarjan(i);
}
for(int i = 1; i <= n; i++)
{
for(int j = 0; j < mapp[i].size(); j++)
{
int v = mapp[i][j];
if(color[i] != color[v])
{
pene[color[v]] ++;//计算入度
}
}
}
int ct = 0,ans = 0;
for(int i = 1; i <= sig; i++)
{
if(pene[i] > 0)continue;
ans+= fun(i);
ct ++;
}
printf("%d %d\n", ct, ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: