【9002】局域網

Time Limit: 1 second
Memory Limit: 256 MB網絡

問題描述
某個局域網內有n(n<=100)臺計算機,因爲搭建局域網時工做人員的疏忽,如今局域網內的鏈接造成了迴路,咱們知道若是局域網造成迴路那麼數據將不聽的在迴路內傳輸,形成網路卡的現象。由於鏈接計算機的網線自己不一樣,因此有一些連線不是很暢通,咱們用f(i,j)表示i,j之間鏈接的暢通程度(f(i,j)<=1000),f(i,j)值越小表示i,j之間鏈接越通暢,f(i,j)爲0表示i,j之間無網線鏈接。如今咱們須要解決迴路問題,咱們將除去一些連線,使得網絡中設有迴路,而且被除去網線的∑f(i,j)最大,請求出這個最大值。     函數

Input

第一行兩個正整數n,k,接下來的k行每行三個正整數i、j、m表示i、j兩臺計算機之間有網線聯通,通暢程度爲m。 spa

Output

一個正整數,∑f(i,j)的最大值
code

Sample Input

5 5
1 2 8
1 3 1
1 5 3
2 4 5
3 4 2

Sample Output

8 

【題解】排序

若是最後剩餘的網線,恰好夠n臺電腦鏈接,且少一條線都不行。那麼這樣的連線方式確定是最佳的。也即用n-1條線鏈接n臺電腦。而後保證這n-1條線是最優的便可。關於克魯斯卡爾的貪心策略。咱們順序排了一下。get

咱們在找順序找邊的時候,考慮一下,若是當前邊能夠鏈接兩個不一樣的集合。而你不選,那麼以後的邊若是能鏈接這兩個集合,那麼確定要付出更大的花費。確定不如就選這條邊的方案優。input

【代碼】it

#include <cstdio>
#include <algorithm>

using namespace std;

struct edge //用結構體 進行排序比較方便。 
{
	int fr,to,w;
};

int su,su2,n,k,f[101],tt = 0; //su是全部一開始全部網絡的累加和 su2是最小生成樹的累加和 
edge a[10001];

void input_data()
{
	scanf("%d%d",&n,&k);
	for (int i = 1;i <= n;i++) //並查集的初始化操做 
		f[i] = i;
	for (int i = 1;i <= k;i++)
		{
			scanf("%d%d%d",&a[i].fr,&a[i].to,&a[i].w);
			su+=a[i].w;
		}
}

int findfather(int x) //並查集用來尋找根節點的操做,同時壓縮路徑 
{
	if (f[x]!=x)
		f[x] = findfather(f[x]);
	return f[x];
}

int cmp(const edge & a,const edge & b) //sort函數的比較函數在algorithm頭文件中 
{
	if (a.w < b.w) //不等號決定了你的排序是如何排的 
		return 1;
	return 0;
}

void get_ans()
{
	for (int i = 1;i <= k;i++) //枚舉k條邊同時累加MST的和 
		{
			int x= a[i].fr,y = a[i].to;
			int r1 = findfather(x),r2 = findfather(y); //若是能聯通這兩個區域,就連同,由於後面若是再出現
			//一條邊也能連同這個兩個區域,所需的花費確定更大了! 
			if (r1!=r2)
				{
					f[r2] = r1;
					su2+=a[i].w;
					tt++;
					if (tt == n-1) //找到n-1條邊了就結束。 
						return;
				}
		}
}

void output_ans()
{
	printf("%d",su-su2);	
}

int main()
{
	//freopen("F:\\rush.txt","r",stdin);
	input_data();
	sort(a+1,a+1+k,cmp);
	get_ans();
	output_ans();
	return 0;	
}
相關文章
相關標籤/搜索