12.6日總結 最小度限制生成樹 POJ 1639(含聯通塊dfs劃分模板)
阿新 • • 發佈:2018-12-21
今天看了 一道 有度數限制的最小生成樹題目,按照書上給出的思路寫的程式碼,思路的最後一步沒有實現,可能沒弄懂書上的意思。
http://poj.org/problem?id=1639。
題意:
大概是說在一張無向圖中找一顆最小生成樹,該樹一定包含某“1”點,且該點的度數不能超過某值。
思路:
先不考慮“1”點,對原圖 dfs劃分聯通塊,然後從每個聯通塊中找一條與“1”最近的路徑新增到答案中。下一步在聯通塊內部求最小生成樹。
最後,遍歷“1”點的所有邊,如果某條邊指向的終點不是已經生成的生成樹的起點,判斷其是否小於 已有生成樹中從該點到“1”點路徑中的最長邊長度。有,替換舊邊,,,直到找不到這樣的邊(最後這個地方理解的還有點問題)。
先把沒寫完的程式碼放在這裡:
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include<algorithm> #include <set> #include <queue> #include <stack> #include<vector> #include<map> #include<ctime> #define ll long long using namespace std; const int N=36; int v[N];//聯通塊標號 int ver[N];//鄰接表邊N的終點 int edge[N*N+100];//鄰接表邊N的權值 int head[N];//鄰接表點N的最後一條邊 int next[N];//鄰接表點邊N的下一條邊 int tot;//鄰接表 中邊數 int cnt;//聯通塊的數目 void add(int x,int y,int z)//鄰接表加邊 { ver[++tot]=y; edge[tot]=z; next[tot]=head[x]; head[x]=tot; } void dfs(int x)//得到x所在的聯通塊 { v[x]=cnt; for(int i=head[x];i;i=next[i]) { int y=ver[i]; if(v[y])continue; dfs(y); } } int dis[N][N]; map<string,int>mm; int num; int d[N];//prime中以點N為終點的那條邊; bool flag[N]; int prime(int index,int pos,int nn)//聯通塊標號、起點 { memset(d,0,sizeof(d)); memset(flag,0,sizeof(flag)); d[pos]=0; for(int i=1;i<nn;++i) { int x=0; for(int j=1;j<=num;++j) if(!flag[j]&&((x==0)||d[j]<d[x])&&v[j]==index)x=j; flag[x]=1; for(int y=1;y<=num;++y) { if(!flag[y]&&v[y]==index)d[y]=min(d[y],dis[x][y]); } } int ans=0; for(int i=1;i<=num;++i) { if(v[i]==index)ans+=d[i]; } return ans; } int main() { int n; while(cin>>n) { memset(dis,0,sizeof(dis)); tot=cnt=0; mm.clear(); memset(v,0,sizeof(v)); memset(ver,0,sizeof(ver)); memset(head,0,sizeof(head)); memset(next,0,sizeof(next)); memset(edge,0,sizeof(edge)); string s,t; int x; mm.insert(make_pair("Park",1)); num++; for(int i=1;i<=n;++i) { cin>>s>>t>>x; int d1,d2; if(mm.find(s)==mm.end()) { num++; mm.insert(make_pair(s,num)); d1=num; } else { d1=mm.find(s)->second; } if(mm.find(t)==mm.end()) { num++; mm.insert(make_pair(t,num)); d2=num; } else { d2=mm.find(t)->second; } dis[d1][d2]=dis[d2][d1]=x; add(d1,d2,x); } int s; cin>>s; for(int i=2;i<=num;++i) { if(v[i])continue; cnt++; dfs(i); } /*if(cnt>s) { //無解 }*/ int ans=0; for(int i=1;i<=cnt;++i) { int minn=999999999; int pos; for(int j=1;j<=num;++j) { int nn=0; if(v[j]==i) { nn++; if(dis[j][1]<minn)minn=dis[j][1],pos=j; } } if(minn!=999999999)ans+=minn; ans+=prime(i,pos,nn); } } }