HDU 1827 强联通缩点

来源:互联网 发布:java中的单例设计模式 编辑:程序博客网 时间:2024/05/03 04:01


输入n、m ,n表示人数和m是联系对数。每对人的联系时单向且可以传递,联系不同人的花费不同,需要找到花费最少为多少。


题解:强联通缩点,保存强联通分块所有节点的最小权值,入度为零的即为需要联系的联通分块

#include<cstdio>#include<stdlib.h>#include<string.h>#include<string>#include<map>#include<cmath>#include<iostream>#include <queue>//#include <stack>#include<algorithm>#include<set>using namespace std;#define INF 1e8#define eps 1e-8#define LL __int64#define maxn 26#define mol 1000000007#define N 1010#define M 2010struct Edge  {  int v;  int next;  };  Edge edge[M];//边的集合  int node[N];//顶点集合  int instack[N];//标记是否在stack中  int stack[N];  int Belong[N];//各顶点属于哪个强连通分量  int DFN[N];//节点u搜索的序号(时间戳)  int LOW[N];//u或u的子树能够追溯到的最早的栈中节点的序号(时间戳)  int n, m;//n:点的个数;m:边的条数  int cnt_edge;//边的计数器  int Index;//序号(时间戳)  int top;  int Bcnt;//有多少个强连通分量  int in[N],out[N],numd[N],c[N];void add_edge(int u, int v)//邻接表存储  {  edge[cnt_edge].next = node[u];  edge[cnt_edge].v = v;  node[u] = cnt_edge++;  }  void tarjan(int u)  {  int i, j;  int v;  DFN[u] = LOW[u] = ++Index;  instack[u] = true;  stack[++top] = u;  for (i = node[u]; i != -1; i = edge[i].next)  {  v = edge[i].v;  if (!DFN[v])//如果点v没被访问//树枝边  {  tarjan(v);  if (LOW[v]<LOW[u])  LOW[u] = LOW[v];  }  else//如果点v已经被访问过//后向边  if (instack[v] && DFN[v]<LOW[u])  LOW[u] = DFN[v];  }  if (DFN[u] == LOW[u])//缩点  {  Bcnt++;  do  {  j = stack[top--];  instack[j] = false;  Belong[j] = Bcnt;  if(c[j]<numd[Bcnt])numd[Bcnt]=c[j];//保存分块的最小权值} while (j != u);  }  }  void solve()  {  int i;  top = Bcnt = Index = 0;  memset(DFN, 0, sizeof(DFN));  memset(LOW, 0, sizeof(LOW));  memset(Belong, 0, sizeof(Belong)); for (i = 1; i <= n; i++)  if (!DFN[i])  tarjan(i);  }  int main()  {  //freopen("in.txt", "r", stdin);  int i, j, k, t;  while(~scanf("%d%d",&n,&m)){cnt_edge = 0;  for(i=1;i<=n;i++){scanf("%d",&c[i]);numd[i]=INF;}memset(node, -1, sizeof(node));  for (i = 1; i <= m; i++)  {  scanf("%d%d", &j,&k);add_edge(j,k);  }  solve();  memset(in,0,sizeof(in));memset(out,0,sizeof(out));//memset(numd,127,sizeof(numd));for(i=1;i<=n;i++){for(j=node[i];j!=-1;j=edge[j].next ){if(Belong[i]!=Belong[edge[j].v]){in[Belong[edge[j].v]]++;out[Belong[i]]++;}}}int a=0,b=0;for(j=1;j<=Bcnt;j++){if(!in[j]) //入度为零{b+=numd[j];a++;}}printf("%d %d\n",a,b);}return 0;  }  /*12 161 2 3 4 5 6 7 8 9 10 11 121 33 22 13 42 43 55 44 66 47 47 127 88 78 910 911 10*/


0 0
原创粉丝点击