Summer Holiday
Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2380 Accepted Submission(s): 1118
Problem Description
To see a World in a Grain of Sand
And a Heaven in a Wild Flower,
Hold Infinity in the palm of your hand
And Eternity in an hour.
—— William Blake
听说lcy帮大家预定了新马泰7日游,Wiskey真是高兴的夜不能寐啊,他想着得快点把这消息告诉大家,虽然他手上有所有人的联系方式,但是一个一个联系过去实在太耗时间和电话费了。他知道其他人也有一些别人的联系方式,这样他可以通知其他人,再让其他人帮忙通知一下别人。你能帮Wiskey计算出至少要通知多少人,至少得花多少电话费就能让所有人都被通知到吗?
And a Heaven in a Wild Flower,
Hold Infinity in the palm of your hand
And Eternity in an hour.
—— William Blake
听说lcy帮大家预定了新马泰7日游,Wiskey真是高兴的夜不能寐啊,他想着得快点把这消息告诉大家,虽然他手上有所有人的联系方式,但是一个一个联系过去实在太耗时间和电话费了。他知道其他人也有一些别人的联系方式,这样他可以通知其他人,再让其他人帮忙通知一下别人。你能帮Wiskey计算出至少要通知多少人,至少得花多少电话费就能让所有人都被通知到吗?
Input
多组测试数组,以EOF结束。
第一行两个整数N和M(1<=N<=1000, 1<=M<=2000),表示人数和联系对数。
接下一行有N个整数,表示Wiskey联系第i个人的电话费用。
接着有M行,每行有两个整数X,Y,表示X能联系到Y,但是不表示Y也能联系X。
第一行两个整数N和M(1<=N<=1000, 1<=M<=2000),表示人数和联系对数。
接下一行有N个整数,表示Wiskey联系第i个人的电话费用。
接着有M行,每行有两个整数X,Y,表示X能联系到Y,但是不表示Y也能联系X。
Output
输出最小联系人数和最小花费。
每个CASE输出答案一行。
每个CASE输出答案一行。
Sample Input
12 16 2 2 2 2 2 2 2 2 2 2 2 2 1 3 3 2 2 1 3 4 2 4 3 5 5 4 4 6 6 4 7 4 7 12 7 8 8 7 8 9 10 9 11 10
Sample Output
3 6
强联通分量模板题
#include<bitset>
#include<map>
#include<vector>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<stack>
#include<queue>
#include<set>
#define inf 0x3f3f3f3f
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
inline int in()
{
int res=0;char c;
while((c=getchar())<'0' || c>'9');
while(c>='0' && c<='9')res=res*10+c-'0',c=getchar();
return res;
}
const int N=1002;
vector<int> v[N];
int dfn[N],low[N],Stack[N],cost[N],rd[N],scc[N],cnt,n,m,top,dfs_num;
void init()
{
for(int i=1;i<=n;i++)
{
v[i].clear();
}
mem(dfn,0);
mem(rd,0);
mem(scc,0);
dfs_num=0;
top = 0;
cnt = 0;
}
void tarjan(int x)
{
low[x] = dfn[x] = ++dfs_num;
Stack[++top] = x;
for(int i=0;i<(int)v[x].size();i++)
{
int t = v[x][i];
if(!dfn[t])
{
tarjan(t);
low[x] = min(low[t],low[x]);
}
else if(!scc[t] && dfn[t] < low[x])
low[x] = dfn[t];
}
if(dfn[x] == low[x])
{
cnt++;
while(1)
{
int t=Stack[top--];
scc[t]=cnt;
if(x==t) break;
}
}
}
int fun(int x)
{
int ret=inf;
for(int i=1;i<=n;i++)
{
if(scc[i] == x) ret=min(cost[i],ret);
}
return ret;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
{
cost[i]=in();
}
for(int i=0;i<m;i++)
{
int x=in(),y=in();
v[x].push_back(y);
}
for(int i=1;i<=n;i++)
{
if(dfn[i] == 0) tarjan(i);
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<(int)v[i].size();j++)
{
int t=v[i][j];
int x=scc[i];
int y=scc[t];
if(x==y) continue;
rd[y]++;
}
}
int sum=0,count=0;
for(int i=1;i<=cnt;i++)
{
if(rd[i] == 0)
{
sum += fun(i);
count++;
}
}
printf("%d %d\n",count,sum);
init();
}
return 0;
}