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


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

最短路樹顧名思義,就是從一個圖中生成出來一棵樹,使得每個頂點到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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM