1. 程式人生 > >POJ 1797 Heavy Transportation(最大生成樹)

POJ 1797 Heavy Transportation(最大生成樹)

題目大意:給定n個頂點,以及m條邊的描述,每條邊的描述包括:起點、終點、權重。現在要從頂點1出發到達頂點n,求路徑中能夠承受的最大權重。

解題思路:讀懂題意很重要,樣例比較水,要去深入理解題目,同時注意輸出格式。

1)本題要求出的是從頂點1到頂點n的所有可行路徑中各邊權值的最小值的最大值。即max(min(可行路徑邊))。很顯然是最短路徑的變形。

2)Prim演算法:其實就是找一條帶權路徑,使得路徑上最小的權值最大化,只要求一次最大生成樹即可,沒有什麼複雜的演算法,不過這個題要對最小生成樹有更深的理解

prim演算法:
1、設有一集合S,首先,將起點s(最後就成了最小生成樹的根節點)放入集合,則S = {s}
2、找到距離集合S最近的一點u,加入S集合
3、通過點u,更新其餘未進入集合S的點到集合S的距離
4、如果集合S外沒有點了,結束,否則轉到步驟2
其實整個過程中就是在找到一個距離起點集合S路徑最小的點,加入進來,然後不斷更新,這就像在建一棵連通樹,在保證連通的情況下,不斷的加入新的葉子節點,由於每次入的邊權最小,所以最後建成的就是一棵最小生成樹,它能保證起點到任意一點的路徑上最小的權值最小化;同理,最大生成樹就是在加點的時候找權值最大的加入就行了。

好多方法都能過,主要是題意的理解,SPFA,最短路,等。

最短路演算法:

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<stdlib.h>
#include<math.h>
#include<queue>
#include<map>
#include<stack>
#define mann 1008
#define INF 1000000001
typedef long long LL;
using namespace std;
int n,m;
int vis[mann],dis[mann];
int mp[mann][mann];
void dijstra(int cur)
{
    for(int i=1;i<=n;i++)
    {
        dis[i]=mp[cur][i];
        vis[i]=0;
    }
    dis[cur]=0;
    vis[cur]=1;
    int minn,pos,ans=INF;
    for(int i=1;i<n;i++)
    {
        minn=-2;
        for(int j=1;j<=n;j++)
        {
          if(!vis[j]&&dis[j]>minn)
          {
              minn=dis[j];
              pos=j;
          }
        }
        vis[pos]=1;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&dis[j]<min(mp[pos][j],dis[pos]))
                dis[j]=min(mp[pos][j],dis[pos]);
        }
    }
}
int main()
{
    int t,T=0;
    scanf("%d",&t);
    while(t--)
    {
        int u,v,w;
        memset(dis,0,sizeof(dis));
        memset(mp,0,sizeof(mp));//注意資料的初始化
        scanf("%d%d",&n,&m);
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d",&u,&v,&w);
                mp[u][v]=mp[v][u]=w;
        }
        dijstra(1);
        printf("Scenario #%d:\n%d\n\n",++T,dis[n]);
    }
}

prim演算法:

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
using namespace std;
#define mann 1005
#define INF 0x3f3f3f3f
int aa[mann],mp[mann][mann];
int vis[mann],low[mann];
int n,m;
int prim()
{
    memset(vis,0,sizeof(vis));
    int pos=1,sum=0,minn;
    vis[pos]=1;
    low[pos]=0;
    for(int i=1;i<=n;i++)
    {
        if(i!=pos)
        low[i]=mp[pos][i];
    }
    for(int i=0;i<n;i++)
    {
        minn=-INF;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&low[j]>minn)
            {
                minn=low[j];
                pos=j;
            }
        }
        sum=min(minn,sum);
        if(pos==n)
            break;//並不一定要走完所有的點,走到終點就行
            vis[pos]=1;
            //printf("%d*%d\n",pos,minn);
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&low[j]<mp[pos][j])
                low[j]=mp[pos][j];
        }
    }
    return sum;
}
int main()
{
    int t,T=0   ;
    scanf("%d",&t);
    while(t--)
    {
        memset(mp,-INF,sizeof(mp));
        int a,b,c;
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            mp[a][b]=mp[b][a]=c;
        }
        printf("Scenario #%d:\n%d\n\n",++T,prim());
    }
}

Kruskal:

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<map>
#include<queue>
typedef long long LL;
using namespace std;
#define INF 0x3f3f3f3f
const int maxn=1000005;
int set[maxn];
int n,m;
struct node
{
    int u,v,w;
} c[maxn];
bool cmp(node aa,node bb)
{
    return aa.w>bb.w;
}
int find(int x)
{
    return set[x]==x?x:find(set[x]);
}
int merge(int x,int y)//判斷是否屬於同一個集合
{
    int fx=find(x);
    int fy=find(y);
    if(fx!=fy)
        return 1;//不屬於
    return 0;//屬於
}
int Kruskal()
{
    int maxx=INF;
    sort(c,c+m,cmp);
    for(int i=0; i<m; i++)
    {
        if(merge(c[i].v,c[i].u))//不屬於同一個集合
        {
            maxx=min(maxx,c[i].w);//更新最小值
            set[find(c[i].v)]=find(c[i].u);//合併到同一集合
        }
         if(!merge(1,n))//判斷1、n是否在同一集合,如果在,可以直接從1~n,跳出
            break;
    }
    return maxx;
}
void init()
{
    for(int i=1; i<=n; i++)
        set[i]=i;
}
int main()
{
    int t,T=0;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        init();
        for(int i=0; i<m; i++)
            scanf("%d%d%d",&c[i].u,&c[i].v,&c[i].w);
        int ans=Kruskal();
        printf("Scenario #%d:\n%d\n\n",++T,ans);
    }
    return 0;
}

相關推薦

POJ 1797 Heavy Transportation成樹

題目大意:給定n個頂點,以及m條邊的描述,每條邊的描述包括:起點、終點、權重。現在要從頂點1出發到達頂點n,求路徑中能夠承受的最大權重。 解題思路:讀懂題意很重要,樣例比較水,要去深入理解題目,同時注意輸出格式。 1)本題要求出的是從頂點1到頂點n的所有可行路徑中各邊權值

poj 2377 Bad Cowtractors 成樹

Bessie has been hired to build a cheap internet network among Farmer John's N (2 <= N <= 1,000) barns that are conveniently numbe

POJ-1797 Heavy Transportation短路變形

                                                Heavy Transportation Time Limit: 3000MS Memory Limit: 30000K Total Submissions: 

Heavy Transportation成樹

Heavy TransportationTime Limit: 3000MSMemory Limit: 30000KTotal Submissions: 43148Accepted: 11340DescriptionBackground Hugo Heavy is happy

Bad Cowtractors成樹

found ins -m 普裏姆算法 卡爾 eal following void HR Description Bessie has been hired to build a cheap internet network among Farmer John

POJ 1797 Heavy Transportation短路思維+承載】

The first line contains the number of scenarios (city plans). For each city the number n of street crossings (1 <= n <= 1000) and number m of stree

poj 1797Heavy Transportation(成樹

Heavy Transportation Time Limit: 3000MS   Memory Limit: 30000K

貨車運輸成樹+LCA

整數 fine std 一個 ext getchar() 最小路徑 ont getch 題目描述 A 國有 n 座城市,編號從 1 到 n,城市之間有 m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 q 輛貨車在運輸貨物, 司機們想知道每輛車在不超過車輛限重

ACM_他和她成樹+短路徑

遇到 否則 ret 所有 end 接下來 這樣的 機房 那種 他和她 Time Limit: 2000/1000ms (Java/Others) Problem Description: 大二上學期剛過完,平時成績不錯的小V參加了一個小型編程比賽,遇到一道題,雖然

「NOIP2013」「LuoguP1967」貨車運輸成樹 倍增 LCA 「LuoguP4180」 【模板】嚴格次小生成樹[BJWC2010]倍增 LCA Kruscal

題目描述 AA國有nn座城市,編號從 11到nn,城市之間有 mm 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 qq 輛貨車在運輸貨物, 司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。 輸入輸出格式 輸入格式: &nb

「NOIP2013」「LuoguP1967」貨車運輸成樹 倍增 LCA

!= noi ora 輸出 tdi ott 限制 格式 否則 題目描述 AA國有nn座城市,編號從 11到nn,城市之間有 mm 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 qq 輛貨車在運輸貨物, 司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重

貨車運輸成樹+樹上倍增

題目描述 A 國有 n n n 座城市,編號從

BZOJ4736 溫暖會指引我們前行動態樹+成樹

  類似於瓶頸路,滿足條件的路徑一定在溫度的最大生成樹上,那麼就是一個LCT維護MST的裸題了。 #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #includ

poj-2377模板題,成樹

Bessie has been hired to build a cheap internet network among Farmer John's N (2 <= N <= 1,000) barns that are conveniently numbered

【NOIP 2013 Day1 T3】貨車運輸成樹+LCA

題目描述 Description A 國有 n 座城市,編號從 1 到 n,城市之間有 m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 q 輛貨車在運輸貨物,司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。

POJ-1797 Heavy Transportation(成樹)

ngs accept source total project tween task father then Heavy Transportation Time Limit: 3000MS Memory Limit: 30000K Total Submiss

多能夠承受的重量】poj 1797 Heavy Transportation

Problem Description 輸入T組測試資料,每組測試資料,輸入n,m分別代表n個城市,m條道路接下來m行,每行u,v,w分別代表u,v兩城市之間道路承受的重量。 思路:讓你求出從城市1到城市n最多能夠運輸最大重量,最短路的演算法,改變下

POJ--1797 Heavy Transportation (短路

題目電波: POJ--1797 Heavy Transportation  n點m條邊, 求1到n最短邊最大的路徑的最短邊長度 改進dijikstra,dist[i]陣列儲存源點到i點的最短邊最大的路徑的最短邊長度   #include<iostrea

poj 2377Kruskal演算法 成樹

這道題只是一道模板題,感到唯一的坑點就是n,m容易打錯,一定要注意結構體要開到Max(M)+n; 之前便是因為這個地方Runtime Error了兩次;順便注意最後輸出的答案 為long long型 Kruskal演算法通過把所有的邊從小到大排列後,不斷取權值最

Poj 1797 Heavy Transportation (短路變形)

題意:給你一張圖,有n個點,m條邊。讓你求出從1點到n點的所有通路中最小邊的最大值。 題解:最短路的變形。把dijkstra中dis陣列中存的東西改成最小邊的最大值。每次找最大邊來作比較。然後更新di