HDU 1827 Summer Holiday (强连通分量+缩点)

来源:互联网 发布:我的世界租服务器淘宝 编辑:程序博客网 时间:2024/05/26 02:21

根据题目要求,只需求出各个强连通分量,然后进行缩点。缩点后找出入度为0的点即是需要打的电话数,也就是说找出能覆盖整张关系网的点。因为要求费用最低,所以在求出一个强连通分量时(栈弹出时)找到最小值,记录起来代表该连通分量(即缩点)的值。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <stack>#define SIZE 1001using namespace std;struct node{int to,next;}edge[SIZE<<4];int head[SIZE],idx;int N,M,val[SIZE],ans;int dfsn[SIZE],low[SIZE],time;bool vis[SIZE];int belong[SIZE],num,mincost[SIZE],deg[SIZE];stack <int> sta;void addnode(int from,int to){edge[idx].to = to;edge[idx].next = head[from];head[from] = idx++;}void tarjan(int root){dfsn[root] = low[root] = ++time;sta.push(root);vis[root] = true;for(int i=head[root]; i!=-1; i=edge[i].next){int to = edge[i].to;if(!dfsn[to]){tarjan(to);if(low[to] < low[root])low[root] = low[to];}else if(vis[to] && dfsn[to] < low[root])low[root] = dfsn[to];}int t = 0,tem = 0xfffffff;if(dfsn[root] == low[root]){num ++;while(t != root){t = sta.top();sta.pop();vis[t] = false;belong[t] = num; //同一个强连通分量,缩点tem = min(tem,val[t]); //求最小值}mincost[num] = tem; //将最小值作为该连通分量的代表}}void solve(){memset(dfsn,0,sizeof(dfsn));memset(vis,0,sizeof(vis));memset(deg,0,sizeof(deg));ans = time = num = 0;for(int i=1; i<=N; i++)if(!dfsn[i])tarjan(i);for(int i=1; i<=N; i++)for(int j=head[i]; j!=-1; j=edge[j].next)if(belong[i] != belong[edge[j].to])deg[belong[edge[j].to]] ++;int sum = 0;for(int i=1; i<=num; i++)if(!deg[i]){ans += mincost[i];sum ++;}printf("%d %d\n",sum,ans);}int main(){while(~scanf("%d%d",&N,&M)){for(int i=1; i<=N; i++)scanf("%d",&val[i]);int s,e;idx = 0;memset(head,-1,sizeof(head));for(int i=1; i<=M; i++){scanf("%d%d",&s,&e);addnode(s,e);}solve();}return 0;}


原创粉丝点击