The Unique MST POJ - 1679

10 篇文章 0 订阅
4 篇文章 0 订阅

算次小生成树模板吧,prim的话。。。应该就是更新MAX数组的时候,不是直接=,语句是MAX[u][v] = MAX[v][u] = max(MAX[pre[u]][v], dis[u]);//dis[u] = MAX[u][pre[u]]
 

//心累....第一次拿map做标记,然后,,就遇到问题了,,,拿样例二就会发现,计入map的大小不对....然后,就会发现,由于first是Edge,有三个数,然后,重载的<只有dist,当dist相同时,,他不会计入,样例二刚好就是4个dist都为2....所以a.size会为1,,所以  在重载<的时候,需要==考虑进去........(ps:刚开始还以为是a.clear的问题...改成erase也不对,改成局部成员也不对...)

 

然后,用这个套秦始皇那道题的时候,,会发现,,,MAX少了一部分,是因为更新vector只加入了一部分,另一部分未加入,但是...另一部分也加入的时候在这道题里会出现MLE问题...找到的问题是G的更新用的是原本的u, v节点,实际上应该用的是u,v的根结点。。。改了就AC了...然后  改了也发现,实际上真的只用更新一次G就可以了,MAX也全了....所以,,归根结底,我更新G的时候应该用u,v的根结点...............

AC全面部分

#include<iostream>

#include<cstdio>

#include<queue>

#include<vector>

#include<map> 

#include<cstring>

 

using namespace std;

 

const int N = 1000+5;

const int INF = 0x3f3f3f3f;

 

struct Edge{

    int u, v, dist;

 

    Edge(){

        u = 0;

        v = 0;

        dist = 0;

    };

 

    Edge(int a, int b, int c){

        u = a;

        v = b;

        dist = c;

    }

}edge;

vector<int> G[N];

 

bool operator <(Edge a, Edge b)

{

	if(a.dist == b.dist){//加这个,是因为我用了map来标记,,然后,,first是edge,当dist相等时,,他不加入,,所以,这个语句就是为了标记而用 
		if(a.u == b.u)
			return a.v > b.v;
		return a.u > b.u;

	}

    return a.dist > b.dist;

}

ostream & operator<< (ostream & os, const Edge& A){

	os << A.u << "--" << A.v << "=" << A.dist << endl;

}

priority_queue<Edge> q;

 

int judge[N][N] = {0};

int MAX[N][N];

int pre[N*N/2] = {0};

 

void init(int n)

{

    memset(MAX, 0, sizeof(MAX));

//	a.clear();

//	cout << a.size() << endl;

//	a.erase(a.begin(), a.end());

    for(int i=0; i<=n; i++){

        pre[i] = i;

        G[i].clear();

        G[i].push_back(i); 

    }

}

 

 

 

int Find(int a)

{

    return pre[a] == a ? a : pre[a] = Find(pre[a]);

}

 

void Union(int a, int b)

{
    if(a == b){

        return;

    }

    else{

        pre[a] = b;

 

        return;

    }

 

}

 

void Kruskal(map<Edge, int> ta)

{

 

    int sum = 0, u, v;

 

    while(!q.empty()){

 

        edge = q.top();

        q.pop();

		u = Find(edge.u), v = Find(edge.v); 

        if(u != v){

            sum += edge.dist;

            ta[edge] = 1;//标记 

 

            Union(u, v);

            

            for(int i=0; i<G[u].size(); i++){

            	for(int j=0; j<G[v].size(); j++){

            		MAX[G[u][i]][G[v][j]] = MAX[G[v][j]][G[u][i]] = edge.dist;//边是从小到大排序的,直接等于目前最长的边即可 

				}

			}
			for(int i=0; i<G[u].size(); i++){//因为u为v的子树 

				G[v].push_back(G[u][i]);

			}


 

        }

    }

    

    //cout << sum << endl;

    int Ssum = INF;

    map<Edge, int>::iterator it;

    

    for(it=ta.begin(); it!=ta.end(); it++) {

    //	cout << it->first << endl;

    	if(it->second == 0){//未被标记 

    		int dist=it->first.dist, u=it->first.u, v=it->first.v;

	//		cout << dist << ":" << MAX[u][v] << endl;    		

    		Ssum = min(Ssum, sum+dist-MAX[u][v]); 

		}

	

	}

//	cout << sum << " " << Ssum << endl;
if(Ssum > sum) cout << sum << endl;

	else cout << "Not Unique!" << endl;
}

 

 

 

int main() 

{

	int T;

	

	cin >> T;

	

	while(T--){

		map<Edge, int> a;

    	

		int n, m;

	

		cin >> n >> m;

		 

        while (!q.empty()) {

            q.pop();

        }
 

        init(n);

 

        for (int i = 1; i <= m; i++) {

        	cin >> edge.u >> edge.v >> edge.dist;

            a[edge] = 0;

            q.push(edge);

        }

  //      cout << a.size() << endl;

        Kruskal(a);

	}

 

    return 0;

}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#include <algorithm>

using namespace std;

typedef  long long LL;

const int inf = 0x3f3f3f3f;
const LL N = 100+5;

int n, m;
struct Edge {
    int u, v, w;
}edge[N * N];

int pre[N], rak[N];
int MAX[N][N];
bool vis[N*N];

vector<int> G[N]; //存储MST

void init(int n) {
	memset(vis, 0, sizeof(vis));

    for(int i = 0; i <= n; i++)
        pre[i] = i, rak[i] = 0, G[i].clear(), G[i].push_back(i);
}

int Find(int x) {
    return (x == pre[x])? x : pre[x] = Find(pre[x]);
}

bool Union(int x, int y) 
{
	if(x != y){
		pre[x] = y;
		return true;
	}
	return false;
}	

bool cmp(const Edge &a, const Edge &b) 
{
	return a.w < b.w;
}


void Kruskal() {
    sort(edge+1, edge+1+m, cmp);
    	
	init(N);
    
    int sum = 0;
    for(int i=1; i<=m; i++) {
        int u = Find(edge[i].u), v = Find(edge[i].v), w = edge[i].w;
        if(Union(u, v)) {
            sum += w, vis[i] = true;

            for(int j = 0; j < G[u].size(); ++j)//此处的u,v均为根结点 
                for(int k = 0; k < G[v].size(); ++k)
                    MAX[G[u][j]][G[v][k]] = MAX[G[v][k]][G[u][j]] = w;
 
            for(int j = 0; j < G[u].size(); ++j)
                G[v].push_back(G[u][j]);
        }
    }
    int Ssum = inf;
    for(int i=1; i<=m; ++i)
        if(!vis[i])
            Ssum = min(Ssum, sum+edge[i].w-MAX[edge[i].u][edge[i].v]);
 	if(Ssum > sum) cout << sum << endl;
		else cout << "Not Unique!" << endl;
  //  cout << sum << " " << Ssum << endl;
}

int main() {
    int T;
    cin >> T;
    while(T--){
        cin >> n >> m;
        for(int i=1; i<=m; ++i)
            cin >> edge[i].u >> edge[i].v >> edge[i].w;
        
		Kruskal();
    }
    return 0;
}

 

//*************************蒙对部分.....不严谨..........................

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<map> 
#include<cstring>

using namespace std;

const int N = 1000+5;
const int INF = 0x3f3f3f3f;

struct Edge{
    int u, v, dist;

    Edge(){
        u = 0;
        v = 0;
        dist = 0;
    };

    Edge(int a, int b, int c){
        u = a;
        v = b;
        dist = c;
    }
}edge;
vector<int> G[N];

bool operator <(Edge a, Edge b)
{
	if(a.dist == b.dist){//加这个,是因为我用了map来标记,,然后,,first是edge,当dist相等时,,他不加入,,所以,这个语句就是为了标记而用 
		return a.u > b.u;
	}
    return a.dist > b.dist;
}
ostream & operator<< (ostream & os, const Edge& A){
	os << A.u << "--" << A.v << "=" << A.dist << endl;
}
priority_queue<Edge> q;

int judge[N][N] = {0};
int MAX[N][N];
int pre[N*N/2] = {0};

void init(int n)
{
//    memset(judge, 0, sizeof(judge));
//	a.clear();
//	cout << a.size() << endl;
//	a.erase(a.begin(), a.end());
    for(int i=0; i<=n; i++){
        pre[i] = i;
        G[i].clear();
        G[i].push_back(i); 
    }
}

 

int Find(int a)
{
    return pre[a] == a ? a : pre[a] = Find(pre[a]);
}

void Union(int a, int b)
{
    a = Find(a), b = Find(b);

    if(a == b){
        return;
    }
    else{
        pre[a] = b;

        return;
    }

}

void Kruskal(map<Edge, int> ta)
{

    int sum = 0, u, v;

    while(!q.empty()){

        edge = q.top();
        q.pop();
		u = edge.u, v = edge.v; 
        if(Find(u) != Find(v)){
            sum += edge.dist;
            ta[edge] = 1;//标记 
 
            Union(u, v);
            
            for(int i=0; i<G[u].size(); i++){
            	for(int j=0; j<G[v].size(); j++){
            		MAX[G[u][i]][G[v][j]] = MAX[G[v][j]][G[u][i]] = edge.dist;//边是从小到大排序的,直接等于目前最长的边即可 
				}
			}
			//两个都必须要,不然MAX可能会不全,但是会存在MLE问题... 
			for(int i=0; i<G[u].size(); i++){//因为u为v的子树 
				G[v].push_back(G[u][i]);
			}
/*
			for(int i=0; i<G[v].size(); i++){//因为u为v的子树 
				G[u].push_back(G[v][i]);
			}*/

        }
    }
    
    //cout << sum << endl;
    int Ssum = INF;
    map<Edge, int>::iterator it;
    
    for(it=ta.begin(); it!=ta.end(); it++) {
    //	cout << it->first << endl;
    	if(it->second == 0){//未被标记 
    		int dist=it->first.dist, u=it->first.u, v=it->first.v;
	//		cout << dist << ":" << MAX[u][v] << endl;    		
    		Ssum = min(Ssum, sum+dist-MAX[u][v]); 
		}
	
	}
//	cout << sum << ":" << Ssum << endl;
	
	if(Ssum > sum) cout << sum << endl;
	else cout << "Not Unique!" << endl;

}

 

int main() 
{
	int T;
	
	cin >> T;
	
	while(T--){
		map<Edge, int> a;
    	
		int n, m;
	
		cin >> n >> m;
		 
        while (!q.empty()) {
            q.pop();
        }

        init(n);

        for (int i = 1; i <= m; i++) {
        	cin >> edge.u >> edge.v >> edge.dist;
            a[edge] = 0;
            q.push(edge);
        }
  //      cout << a.size() << endl;
        Kruskal(a);
	}

    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值