1. 程式人生 > >Codeforces 1005F Berland and the Shortest Paths 【最短路樹】【性質】

Codeforces 1005F Berland and the Shortest Paths 【最短路樹】【性質】

std fir 如果 oid nbsp 記錄 iostream codeforce lan

其實是一道裸題,如果沒學過最短路樹的話會比較難做,要想很久想到關鍵性質才能做出來。

最短路樹顧名思義,就是從一個圖中生成出來一棵樹,使得每個頂點到root的距離是單源最短路。如果有這樣的樹的話,那可見這樣的樹是符合題意的。

怎麽生成這樣的樹呢?關鍵在於記錄前驅father,一個距離root最短路是6的點必定從一個距離root最短路是5的點到達(這兩個點之間一定會有一條邊)。所以我們對於所有頂點 2-n,每個頂點u我們找dis[u] = dis[v]+1的情況,這樣的話v就是u的前驅。若v,u之間有一條邊,那u到root的最短路就解決了【因為如果v到root的最短路不變,那u也不變】,原問題就變成了子問題,這就是這麽建樹 正確性的理解。

所有合法前驅記錄完後,我們dfs下枚舉所有前驅就可以了。【最多能生成father[2].size() * father[3].size() * ... * father[n].size()個合法答案】

 1 #include<iostream>
 2 #include<vector>
 3 #include<map>
 4 #include<cstring>
 5 #include<queue>
 6 using namespace std;
 7 
 8 char comp[200005];
 9 vector< pair<int
,int> > edge[200005]; 10 vector<int> father[200005]; 11 vector<string> ans; 12 int dis[200005],n,k; 13 queue< pair<int,int> > q; 14 15 void dfs(int u){ 16 if( ans.size()>=k ) return; 17 if(u==n+1) { ans.push_back(comp+1); return;}//建完了 18 for(int i=0;i<father[u].size();i++){
19 comp[ father[u][i] ] = 1;//從眾多前驅中挑一個 20 dfs(u+1); 21 comp[ father[u][i] ] = 0; 22 } 23 } 24 25 int main(){ 26 int m; cin>>n>>m>>k; 27 for(int i=1;i<=m;i++){ 28 int u,v; scanf("%d %d",&u,&v); 29 edge[u].push_back( make_pair(v,i) ); 30 edge[v].push_back( make_pair(u,i) );//建兩條邊 31 } 32 33 34 memset(dis,-1,sizeof(dis)); 35 for (int i = 1; i <= m; i++) comp[i] = 0; 36 //維護出dis數組 37 q.push( make_pair(1,0) ); dis[1]=0; 38 while(!q.empty()){ 39 pair<int,int> pa = q.front(); q.pop(); 40 int u=pa.first,d=pa.second; 41 for(int i=0;i<edge[u].size();i++){ 42 int v=edge[u][i].first; 43 if( dis[v]==-1 ) { 44 dis[v]=d+1; 45 q.push( make_pair(v,d+1) ); 46 } 47 } 48 } 49 //找最短路數裏每個頂點的前驅 50 for(int i=2;i<=n;i++){ 51 for(int j=0;j<edge[i].size();j++){ 52 if( dis[i]==dis[ edge[i][j].first ]+1 ) father[i].push_back( edge[i][j].second ); 53 } 54 } 55 56 dfs(2);//從2開始建樹 57 if(ans.size()>=k){ 58 cout<<k<<endl; 59 for(int i=0;i<k;i++) cout<<ans[i]<<endl; 60 } 61 else{ 62 cout<<ans.size()<<endl; 63 for(int i=0;i<ans.size();i++) cout<<ans[i]<<endl; 64 } 65 66 67 return 0; 68 }

Codeforces 1005F Berland and the Shortest Paths 【最短路樹】【性質】