NYOJ118 修路方案 次小生成树

来源:互联网 发布:mac系统画流程图 编辑:程序博客网 时间:2024/05/17 22:12

修路方案

时间限制:3000 ms  |  内存限制:65535 KB
难度:5
描述

南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修路。

现在已经知道哪些城市之间可以修路,如果修路,花费是多少。

现在,军师小工已经找到了一种修路的方案,能够使各个城市都联通起来,而且花费最少。

但是,南将军说,这个修路方案所拼成的图案很不吉利,想让小工计算一下是否存在另外一种方案花费和刚才的方案一样,现在你来帮小工写一个程序算一下吧。

输入
第一行输入一个整数T(1<T<20),表示测试数据的组数
每组测试数据的第一行是两个整数V,E,(3<V<500,10<E<200000)分别表示城市的个数和城市之间路的条数。数据保证所有的城市都有路相连。
随后的E行,每行有三个数字A B L,表示A号城市与B号城市之间修路花费为L。
输出
对于每组测试数据输出Yes或No(如果存在两种以上的最小花费方案则输出Yes,如果最小花费的方案只有一种,则输出No)
样例输入
23 31 2 12 3 23 1 34 41 2 22 3 23 4 24 1 2
样例输出
NoYes

求出次小生成树, 判断次小生成树是否等于最小生成树。

次小生成树的求法:http://www.cnblogs.com/hxsyl/p/3290832.html


#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <vector>#include <stack>#include <queue>#include <set>#include <map>#include <list>#include <sstream>#define LL long long#define INF 0x7fffffff#define FIN 0x80000000using namespace std;const int MM = 2139062143;int n, m;int cap[502][502];int mav[502][502], usd[502][502];int dis[502], vis[502], par[502];typedef pair<int, int> Pii;int prim(){    memset(usd, 0, sizeof(usd));    memset(mav, -1, sizeof(mav));    memset(dis, 0x7f, sizeof(dis));    memset(vis, 0, sizeof(vis));    memset(par, -1, sizeof(par));    priority_queue<Pii, vector<Pii>, greater<Pii> > pq;    pq.push(Pii(0, 1));    dis[1] = 0;    int res = 0;    while(pq.size())    {        Pii p = pq.top(); pq.pop();        int u = p.first;        int v = p.second;        if(vis[v]) continue;        vis[v] = 1;        res += u;        if(par[v] != -1)  //第一个结点不需要处理            usd[par[v]][v] = usd[v][par[v]] = 1;  //标记最小生成树用的边        for(int i = 1 ; i <= n ; i++)        {            if(par[v] != -1 && vis[i])                mav[v][i] = mav[i][v] = max(u, mav[i][par[v]]); // v 到 i 的路径的最大边权            if(!vis[i] && cap[v][i] < MM && dis[i] > cap[v][i])            {                dis[i] = cap[v][i];                par[i] = v;  //父亲结点                pq.push(Pii(dis[i], i));            }        }    }    return res;}//暴力枚举每一条边int smst(int res){    int ans = INF;    for(int i = 1 ; i <= n ; i++)        for(int j = i + 1 ; j <= n ; j++)        {            if(cap[i][j] < MM && usd[i][j] == 0)            {                ans = min(ans, res + cap[i][j] - mav[i][j]);            }        }    return ans;}int main(){    int T;    scanf("%d", &T);    while(T--)    {        scanf("%d %d", &n, &m);        //初始化        memset(cap, 0x7f, sizeof(cap));        for(int i = 0 ; i <= n ; i++)            cap[i][i] = 0;        //建图        int u, v, w;        for(int i = 0 ; i < m ; i++)        {            scanf("%d %d %d", &u, &v, &w);            if(cap[u][v] > w)                cap[u][v] = cap[v][u] = w;        }        //得到最小生成树的值        int res = prim();        //判断次小生成树        if(res == smst(res)) cout<<"Yes"<<endl;        else cout<<"No"<<endl;    }}




0 0
原创粉丝点击