(最短路)POJ 3013 - Big Christmas Tree

題意:數據結構

有一張有權無向圖,編號1的點爲根,要求一個生成樹,使得總花費sum(每條邊的花費×子樹全部節點花費的和)最小,輸出這個值。spa

 

分析:code

本身想了半天,永遠離不開生成樹上面,由於以前知道這個題是用最短路作的,想了半天也想不通爲何會是用最大路作的。blog

若是放在現場,本身確定作不出來。get

其實這題主要的思想轉化在於sum(每條邊的花費×子樹全部節點花費的和)這個公式。string

這個公式實際上是等價於sum(每條點的花費×該點到根的邊花費的和)。it

稍微想一想就能明白了。io

其餘的已經沒什麼難度了,無非是最短路而已。class

不過這題有坑,按道理n==0應該是輸出No Answer。queue

由於:

樹狀圖是一種數據結構,它是由n(n>=1)個有限節點組成一個具備層次關係的集合

不過也發現本身的思惟真的很江化,算了,慢慢來。

腦子不夠就用經驗湊。

 

代碼:

 

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <queue>
  5 #include <vector>
  6 
  7 
  8 using namespace std;
  9 
 10 typedef  long long ll;
 11 const ll inf = 1ll<<60;
 12 const int maxn=50010;
 13 
 14 
 15 int t;
 16 int n,m;
 17 ll pa[maxn];
 18 
 19 struct Edge {
 20     int v;
 21     ll c;
 22 };
 23 
 24 struct Node {
 25     int v;
 26     ll c;
 27     Node(int _v,ll _c) {
 28         v=_v,c=_c;
 29     }
 30     bool operator<(const Node &a)const {
 31         return c>a.c;
 32     }
 33 };
 34 
 35 
 36 vector<Edge> edge[maxn];
 37 bool vis[maxn];
 38 ll dist[maxn];
 39 
 40 bool dijkstra(int n,int s) {
 41     memset(vis,false,sizeof(vis));
 42     for(int i=1; i<=n; i++)dist[i]=inf;
 43     priority_queue<Node> pq;
 44     while(!pq.empty())pq.pop();
 45     dist[s]=0;
 46     pq.push(Node(s,0));
 47     int cnt=0;
 48     while(!pq.empty()) {
 49         Node tmp = pq.top();
 50         pq.pop();
 51         int u=tmp.v;
 52         if(vis[u])continue;
 53         cnt++;
 54         vis[u]=true;
 55         for(int i=0; i<edge[u].size(); i++) {
 56             int v = edge[u][i].v;
 57             ll c = edge[u][i].c;
 58             if(!vis[v]&&dist[v]>dist[u]+c) {
 59                 dist[v]=dist[u]+c;
 60                 pq.push(Node(v,dist[v]));
 61             }
 62         }
 63     }
 64     return cnt>=n;
 65 }
 66 
 67 int main() {
 68     scanf("%d",&t);
 69     while(t--) {
 70         for(int i=0; i<=n; i++) {
 71             edge[i].clear();
 72         }
 73         scanf("%d%d",&n,&m);
 74         for(int i=1; i<=n; i++) {
 75             scanf("%lld",&pa[i]);
 76         }
 77         for(int i=0; i<m; i++) {
 78             int u,v;
 79             ll c;
 80             scanf("%d%d%lld",&u,&v,&c);
 81             edge[u].push_back(Edge{v,c});
 82             edge[v].push_back(Edge{u,c});
 83         }
 84         if(n<=1) {
 85             puts("0");
 86             continue;
 87         }
 88         if(dijkstra(n,1)) {
 89             ll ans=0;
 90             for(int i=2; i<=n; i++) {
 91                 ans+=dist[i]*pa[i];
 92             }
 93             printf("%lld\n",ans);
 94         } else {
 95             puts("No Answer");
 96         }
 97 
 98     }
 99 
100 
101     return 0;
102 
103 }
相關文章
相關標籤/搜索