您的位置:首页 > 其它

CSU--1541-- There is No Alternative

2015-11-12 14:18 253 查看

</pre>1541: There is No Alternative</h2><span class="green">Time Limit: </span>3 Sec  <span class="green">Memory Limit: </span>256 MB<span class="green">Submit: </span>259  <span class="green">Solved: </span>67[<a target=_blank href="http://acm.csu.edu.cn/OnlineJudge/submitpage.php?id=1541" target="_blank">Submit</a>][<a target=_blank href="http://acm.csu.edu.cn/OnlineJudge/problemstatus.php?id=1541" target="_blank">Status</a>][<a target=_blank href="http://acm.csu.edu.cn/OnlineJudge/bbs.php?pid=1541" target="_blank">Web Board</a>]</center><h2>Description</h2><div class="content"><p><img alt="" src="http://acm.csu.edu.cn/OnlineJudge/upload/201503/Alternative1.jpg" /> </p></div><h2>Input</h2><div class="content"><p><img width="364" height="43" alt="" src="http://acm.csu.edu.cn/OnlineJudge/upload/201503/Alternative2.jpg" /> <img width="750" height="642" alt="" src="http://acm.csu.edu.cn/OnlineJudge/upload/201503/Alternative3.jpg" /></p></div><h2>Output</h2><div class="content"><p> <img width="758" height="71" alt="" src="http://acm.csu.edu.cn/OnlineJudge/upload/201503/Alternative4.jpg" /></p></div><h2>Sample Input</h2><pre class="content"><span class="sampledata">4 4
1 2 3
1 3 3
2 3 3
2 4 3</span>
Sample Output

1 3
题意:要求构造最小生成树的边中,哪些边是必需的(即删去这条边再构造最小生成树得出的总权值发生了改变),并输出这些边的数目和总权值。
思路:先构造最小生成树,记录总权值sumWeight和使用的边的下标(存入数组used[]),再依次去掉每条边,重新构造最小生成树(注意初始化),比较每次构造的最小生成树的总权值weight,如果与sumWeight不相等,则表示该边不能去掉。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>int flag[55000], n, used[55000];struct node{int s, d, c;}road[55000];bool cmp(const node& a, const node& b){return a.c<b.c;}void init(){for(int i=1; i<=n; i++)flag[i]=i;        //初始化根节点为其本身的下标}int find(int x)//找该点所属的集合的根节点{return x==flag[x] ? x : flag[x]=find(flag[x]);}using namespace std;int main(){#ifdef OFFLINEfreopen("t.txt","r",stdin);#endifint m, i, j;scanf("%d %d", &n, &m);i=1;   j=m;while(j--){scanf("%d %d %d", &road[i].s, &road[i].d, &road[i].c);i++;}sort(road+1, road+i, cmp); //按权值小到大排序init();int num=0, sumWeight=0, p=1, L, R;for(i=1; i<=m; i++){L=find(road[i].s), R=find(road[i].d);if(L != R){                 //分属两个不同连通分量used[p++]=i;       //记录第一次构造最小生成树的边下标flag[L]=R;        //改变L的根节点即合并两个集合num++;           //统计已加入边的数目sumWeight+=road[i].c;}if(num==n-1)  break;}int cost=0, weight=0, Num=0;for(i=1; i<p; i++){   //依次减去一条边重新构造最小生成树weight=0,     num=0, 	init(); //初始化for(j=1; j<=m; j++){if(j != used[i]){L=find(road[j].s), R=find(road[j].d);if(L != R){num++;flag[L]=R;weight+=road[j].c;}if(num==n-1)  break;}}if(sumWeight != weight){//不相等说明该边不能省去Num++, cost+=road[used[i]].c;//加该边权值(注意该条边下标是used[i])}}printf("%d %d\n", Num, cost);return 0;}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: