【Codeforces 1005F]バーランドと最短経路(最短経路ツリー+ DFS)

【Codeforces 1005F]バーランドと最短経路(最短経路ツリー+ DFS)

フェイス質問

質問の意味:他の点への最短距離となるようスパニングツリーを見つけるために、開始点として、あなたの開始点を無向グラフ1を与えるために、最小距離は、複数のスパニングツリーを有することができます。kはプログラムの数は完全なプログラム、プログラムのそれ以外の場合は、出力のk種類の出力よりも小さい場合、kは所与。

分析

最短Xianpaoは、各点の最短父親ツリーでそれを見つける。ためのものであることを\ \((x、y)が Eで、DIST(Y)= DIST(X)+ LEN(x、y)を\ 最短経路木が一意ではないかもしれないので、次に最短の方法で可能父親は「おそらく」のx。Yと答えています。

DFSはその後、彼の父は、答えは出力することができ、各クリックを列挙します。

コード

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define maxn 300000
#define maxm 300000
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std; 
typedef long long ll;
int n,m,k;
struct edge {
    int from;
    int to;
    int next;
    int id;
    int type;
} E[maxm*2+5];
int head[maxn+5];
int esz=1;
void add_edge(int u,int v,int id) {
    esz++;
    E[esz].from=u;
    E[esz].to=v;
    E[esz].next=head[u];
    E[esz].id=id;
    head[u]=esz;
}
 
struct node {
    int id;
    ll dist;
    node() {
 
    }
    node(int _id,ll _dist) {
        id=_id;
        dist=_dist;
    }
    friend bool operator < (node p,node q) {
        return p.dist>q.dist;
    }
};
int pre[maxn+5];
bool vis[maxn+5];
ll dist[maxn+5];
void dijkstra(int s) {
    priority_queue<node>q;
    memset(vis,0,sizeof(vis));
    memset(dist,0x3f,sizeof(dist));
    dist[s]=0;
    q.push(node(s,0));
    while(!q.empty()) {
        int x=q.top().id;
        q.pop();
        if(vis[x]) continue;
        vis[x]=1;
        for(int i=head[x]; i; i=E[i].next) {
            int y=E[i].to;
            if(dist[y]>dist[x]+1) {
                dist[y]=dist[x]+1;
                pre[y]=i;
                if(!vis[y]) q.push(node(y,dist[y]));
            }
        }
    }
//  for(int i=1; i<=n; i++) {
//      if(pre[i]) E[pre[i]].type=E[pre[i]^1].type=1;
//  }
}
 
vector<int>T[maxn+5]; 
int cnt=0;
vector<string>ans;
string now;
void dfs(int x){//搜索每个点的前驱 
    if(ans.size()>=k) return;
    if(x>n){
        ans.push_back(now);
        return;
    }
    for(int i=0;i<T[x].size();i++){
        //枚举选哪个前驱
//      printf("db: %d\n",T[x][i]);
        now[T[x][i]-1]='1';
        dfs(x+1);
        now[T[x][i]-1]='0'; 
    }
} 
int main() {
    int u,v;
    scanf("%d %d %d",&n,&m,&k);
    for(int i=1;i<=m;i++){
        scanf("%d %d",&u,&v);
        add_edge(u,v,i);
        add_edge(v,u,i);
    }
    dijkstra(1);
    for(int i=2;i<=esz;i++){
        int x=E[i].from;
        int y=E[i].to;
        if(dist[y]==dist[x]+1){
            T[y].push_back(E[i].id);
            //找每个点的前驱 
            //注意不是x而是id 
        }
    }
    now.resize(m);
    for(int i=0;i<m;i++) now[i]='0';
    dfs(2);//从2开始搜索前驱
    printf("%d\n",ans.size());
    for(int i=0;i<ans.size();i++){
//      for(int j=0;j<ans[i].length();j++) putchar(ans[i][j]);
        cout<<ans[i];
        putchar('\n');
    } 
}

おすすめ

転載: www.cnblogs.com/birchtree/p/11966035.html
おすすめ