Summer Holiday(强联通入度最小点)
Summer Holiday
Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2319 Accepted Submission(s): 1082
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
题解:每个强联通分量均可以访问到此联通图的每个成员,还可以访问下一个强联通分量,所以加一个入度,另开一个数组找此强联通分量的最小值;
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<stack> 7 #include<vector> 8 using namespace std; 9 const int INF=0x3f3f3f3f; 10 //#define LOCAL 11 #define mem(x,y) memset(x,y,sizeof(x)) 12 const int MAXN=1010; 13 int dfs_block,css; 14 int dfn[MAXN],low[MAXN],Instack[MAXN],pre[MAXN],minicost[MAXN],in[MAXN]; 15 vector<int>vec[MAXN]; 16 int cost[MAXN]; 17 stack<int>S; 18 void initial(){ 19 mem(dfn,0);mem(low,0);mem(Instack,0);mem(pre,0);mem(minicost,INF);mem(in,0); 20 for(int i=0;i<MAXN;i++)vec[i].clear(); 21 while(!S.empty())S.pop(); 22 css=dfs_block=0; 23 } 24 void targin(int u,int fa){ 25 dfn[u]=low[u]=++dfs_block; 26 S.push(u); 27 Instack[u]=1; 28 for(int i=0;i<vec[u].size();i++){ 29 int v=vec[u][i]; 30 if(!dfn[v]){ 31 targin(v,u); 32 low[u]=min(low[u],low[v]); 33 } 34 else if(Instack[v])low[u]=min(low[u],dfn[v]);//v写成了u... 35 } 36 if(dfn[u]==low[u]){ 37 css++; 38 while(1){ 39 int v=S.top(); 40 S.pop(); 41 Instack[v]=0; 42 pre[v]=css; 43 if(u==v)break; 44 } 45 } 46 } 47 int main(){ 48 #ifdef LOCAL 49 freopen("data.in","r",stdin); 50 freopen("data.out","w",stdout); 51 #endif 52 int N,M; 53 while(~scanf("%d%d",&N,&M)){ 54 initial(); 55 for(int i=1;i<=N;i++)scanf("%d",cost+i); 56 int a,b; 57 while(M--){ 58 scanf("%d%d",&a,&b); 59 vec[a].push_back(b); 60 } 61 for(int i=1;i<=N;i++){ 62 if(dfn[i])continue; 63 targin(i,-1); 64 } 65 for(int i=1;i<=N;i++){ 66 minicost[pre[i]]=min(minicost[pre[i]],cost[i]);//当前强联通分量的最小值; 67 for(int j=0;j<vec[i].size();j++){ 68 int v=vec[i][j]; 69 if(pre[i]!=pre[v])in[pre[v]]++;//如果这个强联通分量可以由别的强联通分量到达,入度++; 70 } 71 } 72 int ans1=0,ans2=0; 73 for(int i=1;i<=css;i++){ 74 //printf("%d\n",in[i]); 75 if(in[i]==0){ 76 ans1++; 77 ans2+=minicost[i]; 78 } 79 } 80 printf("%d %d\n",ans1,ans2); 81 } 82 return 0; 83 }