日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

1732: 数花费(Kruscal)

發布時間:2024/9/3 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 1732: 数花费(Kruscal) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1732: 數花費
時間限制: 1 Sec 內存限制: 128 MB

[提交][狀態][討論版]
題目描述
 棟棟居住在一個繁華的C市中,然而,這個城市的道路大都年久失修。市長準備重新修一些路以方便市民,于是找到了棟棟,希望棟棟能幫助他。
C市中有n個比較重要的地點,市長希望這些地點重點被考慮。現在可以修一些道路來連接其中的一些地點,每條道路可以連接其中的兩個地點。另外由于C市有一條河從中穿過,也可以在其中的一些地點建設碼頭,所有建了碼頭的地點可以通過河道連接。
棟棟拿到了允許建設的道路的信息,包括每條可以建設的道路的花費,以及哪些地點可以建設碼頭和建設碼頭的花費。
市長希望棟棟給出一個方案,使得任意兩個地點能只通過新修的路或者河道互達,同時花費盡量小。
輸入
輸入的第一行包含兩個整數n, m,分別表示C市中重要地點的個數和可以建設的道路條數。所有地點從1到n依次編號。
接下來m行,每行三個整數a, b, c,表示可以建設一條從地點a到地點b的道路,花費為c。若c為正,表示建設是花錢的,如果c為負,則表示建設了道路后還可以賺錢(比如建設收費道路)。
接下來一行,包含n個整數w_1, w_2, …, w_n。如果w_i為正數,則表示在地點i建設碼頭的花費,如果w_i為-1,則表示地點i無法建設碼頭。
輸入保證至少存在一個方法使得任意兩個地點能只通過新修的路或者河道互達。
輸出
輸出一行,包含一個整數,表示使得所有地點通過新修道路或者碼頭連接的最小花費。如果滿足條件的情況下還能賺錢,那么你應該輸出一個負數。

樣例輸入

5 5 1 2 4 1 3 -1 2 3 3 2 4 5 4 5 10 -1 10 10 1 1

樣例輸出

9

提示

建設第2、3、4條道路,在地點4、5建設碼頭,總的花費為9。

對于20%的數據,1<=n<=10,1<=m<=20,0<=c<=20,w_i<=20;

對于50%的數據,1<=n<=100,1<=m<=1000,-50<=c<=50,w_i<=50;

對于70%的數據,1<=n<=1000;

對于100%的數據,1 <= n <= 10000,1 <= m <= 100000,-1000<=c<=1000,-1<=w_i<=1000,w_i≠0。

來源
/*
跑兩遍kruscal。
第一遍跑沒有碼頭的。
第二遍跑加上碼頭的。
對于第一遍沒有碼頭的而言,可能無法生成最小生成樹。
判斷條件就是: 根節點(pre[i] == i)個數是否等于1
不管帶不帶碼頭跑生成樹,有錢賺的肯定建它啊!!
對于第二遍,由于城市數量最大達10000,碼頭之間的邊無法暴力處理。
此時可以引入一個虛擬節點0,讓所有可以建碼頭的城市通過節點0連接起來。
最后算答案的時候,如果沒有碼頭無法連通,那么就直接取有碼頭的那個答案,
否則取兩者之間較小值。
*/
Ac_code:

#include <bits/stdc++.h>using namespace std; const int maxn= 1e5+5; #define INF 0x3f3f3f3f struct Edge {int s,e;int val;bool operator<(const Edge a)const{return val < a.val;} } data[maxn<<1]; int pre[maxn]; int myFind(int x) {int r = x;while(pre[r]!= r){r = pre[r];}int i = x,j;while(pre[i]!= r){j = pre[i];pre[i] = r;i = j;}return r;//return pre[x]==x?x:pre[x]=myFind(pre[x]); } int kruscal(int n,int m) {for(int i = 1; i <= n; i++){pre[i] = i;}sort(data,data+m);int ans = 0;for(int i = 0; i < m; i++){if(data[i].val == INF) continue; //不能建碼頭int fx = myFind(data[i].s);int fy = myFind(data[i].e);if(fx != fy || data[i].val < 0)//賺錢的路一定建{ans += data[i].val;pre[fx] = fy;}}return ans; } int main() {int n,m;scanf("%d%d",&n,&m);for(int i = 0; i < m; i++){scanf("%d%d%d",&data[i].s,&data[i].e,&data[i].val);}int t;for(int i = m; i < n+m; i++){scanf("%d",&t);data[i].s = 0; //通過虛擬一個0點連接碼頭之間構成的邊data[i].e = i-m+1;if(t == -1)data[i].val = INF;elsedata[i].val = t;}int ans1 = kruscal(n,m); //無碼頭int cnt = 0;for(int i = 1; i <= n; i++)//判斷無碼頭能否連通{if(pre[i]==i) cnt++;}int ans2 = kruscal(n,m+n);//有碼頭printf("%d\n",(cnt==1?min(ans1,ans2):ans2));return 0; }

總結

以上是生活随笔為你收集整理的1732: 数花费(Kruscal)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。