HDOJ--1827--Summer Holiday(强连通分量的最小代价连接)

原创 2015年11月17日 17:35:29

Summer Holiday

Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2368    Accepted Submission(s): 1108


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计算出至少要通知多少人,至少得花多少电话费就能让所有人都被通知到吗?
 

Input
多组测试数组,以EOF结束。
第一行两个整数N和M(1<=N<=1000, 1<=M<=2000),表示人数和联系对数。
接下一行有N个整数,表示Wiskey联系第i个人的电话费用。
接着有M行,每行有两个整数X,Y,表示X能联系到Y,但是不表示Y也能联系X。
 

Output
输出最小联系人数和最小花费。
每个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
 

Author
威士忌
 
思路:就是强连通然后连接强连通分量,找寻到一个最小代价,连通所有的强连通分量。
AC代码:
//两处错误,一处是tarjan算法中的栈定义在了函数内部。 
//第二处错误是solve算法中vector应从j=0处开始遍历。 
#include<stdio.h>
#include<string.h>
#include<stack>
#include<algorithm>
#include<vector>
#define INF 0x3f3f3f
#define MAX 1010*10 //关键还有MAX的大小的确定 
using namespace std;
struct node{//定义邻接表 
	int from,to,next;
}edge[MAX];
int head[MAX],low[MAX],dfn[MAX],cost[MAX];
bool Instack[MAX];
int in[MAX],edgenum;
int scc_cnt,dfs_clock;
int sccno[MAX];
vector<int> NEW[MAX];//储存新图 
vector<int>	scc[MAX];//记录每个强连通内的点。 
int n,m;
stack<int>q;
void init(){//初始化邻接表 
	edgenum=0;
	memset(head,-1,sizeof(head));
}
void addedge(int u,int v){
	node E={u,v,head[u]};
	edge[edgenum]=E;
	head[u]=edgenum++;
}
void getmap(){
	for(int i=1;i<=n;i++)
		scanf("%d",&cost[i]);
	for(int i=0;i<m;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		addedge(a,b);
	}
}
void tarjan(int u){//寻找强连通分量 
	int v;
	low[u] = dfn[u] = ++dfs_clock;//更新初始化low和dfn数组 
	q.push(u);
	Instack[u] = true;
	for(int i = head[u]; i != -1; i = edge[i].next)//深搜每一个节点 
	{
		v = edge[i].to; 
		if(!dfn[v])
		{
			tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if(Instack[v])
		low[u] = min(low[u], dfn[v]); //构建反向边。 
	}

	if(low[u]==dfn[u]){//满足条件的话增加每一个强连通分量 
		scc_cnt++;
		scc[scc_cnt].clear(); 
		while(1){
			v=q.top();
			sccno[v]=scc_cnt;
			scc[scc_cnt].push_back(v);
			q.pop();
			Instack[v]=false;
			if(u==v)//该强连通分量的所有点都出来的话 就跳出。 
				break;
		}
	}
}
void find_cut()
{
	memset(low, 0, sizeof(low));//初始化寻找祖先的数组 
	memset(dfn, 0, sizeof(dfn));//初始化此时能遍历到的数组 
	memset(sccno, 0, sizeof(sccno));//初始化sccno数组,找到每个强连通的点。 
	memset(Instack, false, sizeof(Instack));
	dfs_clock = scc_cnt = 0;//初始化时间戳和强连通数量。 
	for(int i = 1; i <= n; i++)//遍历每一个节点 
	if(!dfn[i]) tarjan(i);
}
void suodian(){
	memset(in,0,sizeof(in));//初始化入度节点 
	for(int i=0;i<edgenum;i++){
		int u=sccno[edge[i].from];
		int v=sccno[edge[i].to];
		if(u!=v){//构建新图。 
			NEW[u].push_back(v);// 新图的边 
			in[v]++;// //新图中每个scc的入度。 
		}	
	}
}
void solve(){
		int mincost=0,temp;//初始化mincost数值。 
		int cnt=0;
		if(scc_cnt==1){
			sort(cost+1,cost+n+1);
			printf("1 %d\n",cost[1]);
		}
		else{
			for(int i=1;i<=scc_cnt;i++){
				if(in[i])//入度为0的才需要构建新边 
					continue;
				cnt++;
				temp=INF;
				for(int j=0;j<scc[i].size();j++)//遍历的时候这一步是从0开始的 
					temp=min(cost[scc[i][j]],temp);//寻找到连接该强连通分量最小的代价 
				mincost+=temp;
			}
				printf("%d %d\n",cnt,mincost);
				
		}
}
int main(){
	while(scanf("%d%d",&n,&m)!=EOF){
		init();
		getmap();//输入地图 
		find_cut();//寻找强连通分量的数目。 
		suodian();//缩点,构造新图。 
		solve();//解决该问题。 
	}
	return 0;
} 
//历时N天,终于总算是把这道题给解决了。心塞塞。无语了。心好累。 
 


版权声明:本文为小小呆原创文章,欲转载,请在后台勾搭本呆。

【强连通分量+缩点】 HDOJ 1827 Summer Holiday

先求出强连通分量,每个强连通分量都可以看成一个点,这个点d

HDOJ 题目1827 Summer Holiday(强连通分量,缩点)

Summer Holiday Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)...

HDU 1827 Summer Holiday 强连通分量缩点

Summer Holiday Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Subm...
  • wr132
  • wr132
  • 2016年03月30日 20:57
  • 299

HDU 1827 Summer Holiday (强连通分量)

题目地址:HDU 1827 先缩点,缩完点后,找出入度为0的块就是需要传递的块。然后用块中花费最少的来当代表块中的花费。累加起来就行了。 代码如下: #include #include #i...

HDU 1827 Summer Holiday(强连通分量)

HDU 1827 Summer Holiday(强连通分量) http://acm.hdu.edu.cn/showproblem.php?pid=1827 题意: 听说lcy帮大家预定了新马泰7日游,...

hdu 1827 Summer Holiday 强连通分量缩点

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1827 题意:听说lcy帮大家预定了新马泰7日游,Wiskey真是高兴的夜不能寐啊,他想着得快点把这消息告...

HDU-1827-Summer Holiday(强连通分量)

F - Summer Holiday Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:327...

HDU1827 Summer Holiday(强连通+缩点+最小传递费用)

题意:给出人物关系图,要把一个通知告诉所有人,告诉每一个人有一个费用,现在想知道最小通知的人与费用。 思路:利用Tarjan算法,对原图进行缩点,然后找出入度为0 的点,那么这个人是必须要通知的,由...

hdoj 1827 Summer Holiday 【有向图 连通最少的点来间接连通所有点】 【tarjan求 SCC + 缩点】

Summer Holiday Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

【HDU】1827 Summer Holiday 强连通缩点

Summer Holiday Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HDOJ--1827--Summer Holiday(强连通分量的最小代价连接)
举报原因:
原因补充:

(最多只允许输入30个字)