cdoj 秋实大哥带我飞 最短路走法 含0权边

//做完这题以后终于理解白书上的边为什么要那样定义了 可以很方便的在o(1) 时间内找到反向边

解法:先跑一边最短路,然后检查最短路上有没有0权边(dfs就好,但是每条边只能走一次,这里就需要用异或找反向边),最后记忆化搜索一遍(每条边也是只能走一次)

  1 #include<cstdio>

  2 #include<iostream>

  3 #include<cmath>

  4 #include<algorithm>

  5 #include<cstring>

  6 #include<cstdlib>

  7 #include<queue>

  8 #include<vector>

  9 #include<map>

 10 #include<stack>

 11 #include<string>

 12 

 13 using namespace std;

 14 

 15 const int INF=1000000000;

 16 const int MOD=1000000009;

 17 

 18 struct Edge{

 19     int from,to,cost;

 20 };

 21 

 22 vector <Edge> edges;

 23 vector <int> G[2007];

 24 bool vis[4000007];

 25 int dis[2007];

 26 bool inq[2007];

 27 int f[2007];

 28 int n,m;

 29 

 30 void AddEdge(int x,int y,int z){

 31     edges.push_back((Edge){x,y,z});

 32     edges.push_back((Edge){y,x,z});

 33     int sz=edges.size();

 34     G[x].push_back(sz-2);

 35     G[y].push_back(sz-1);

 36 }

 37 

 38 void SPFA(){

 39     dis[1]=0;

 40     memset(inq,0,sizeof(inq));

 41     queue<int>q;

 42     q.push(1);

 43     inq[1]=1;

 44     while (!q.empty()){

 45             int now=q.front();

 46             int sz=G[now].size();

 47             q.pop();

 48             for (int i=0;i<sz;i++){

 49                             Edge& e=edges[G[now][i]];

 50                             if (dis[e.to]>dis[now]+e.cost){

 51                                     dis[e.to]=dis[now]+e.cost;

 52                                     if (!inq[e.to]){

 53                                             q.push(e.to);

 54                                             inq[e.to]=1;

 55                                     }

 56                             }

 57             }

 58             inq[now]=0;

 59     }

 60 }

 61 

 62 bool check(int now){

 63     if (now==1) return 1;

 64     bool flag=1;

 65     int sz=G[now].size();

 66     for (int i=0;i<sz;i++){

 67             Edge& e=edges[G[now][i]];

 68             if (!vis[G[now][i]] && dis[now]==dis[e.to]+e.cost){

 69                     vis[G[now][i]]=1;

 70                     vis[G[now][i]^1]=1;

 71                     if (e.cost==0) flag=false;

 72                     if (!check(e.to)) flag=false;

 73             }

 74     }

 75     return flag;

 76 }

 77 

 78 int work(int now){

 79     if (f[now]!=-1) return f[now];

 80     f[now]=0;

 81     int sz=G[now].size();

 82     for (int i=0;i<sz;i++){

 83             Edge& e=edges[G[now][i]];

 84             if (!vis[G[now][i]] && dis[now]==dis[e.to]+e.cost){

 85                     vis[G[now][i]]=1;

 86                     vis[G[now][i]^1]=1;

 87                     f[now]=(f[now]+work(e.to))%MOD;

 88             }

 89     }

 90     return f[now];

 91 }

 92 

 93 

 94 int main(){

 95     scanf("%d%d",&n,&m);

 96     for (int i=1;i<=n;i++) dis[i]=INF;

 97     for (int i=0;i<m;i++){

 98             int x,y,z;

 99             scanf("%d%d%d",&x,&y,&z);

100             AddEdge(x,y,z);

101     }

102     SPFA();

103     //printf("%d\n",dis[n]);

104     memset(vis,0,sizeof(vis));

105     if (!check(n)){

106             printf("-1\n");

107             return 0;

108     }

109     memset(vis,0,sizeof(vis));

110     memset(f,-1,sizeof(f));

111     f[1]=1;

112     printf("%d\n",work(n));

113     return 0;

114 }

115 /*

116 4 4

117 1 2 1

118 1 3 1

119 2 4 2

120 3 4 2

121 

122 4 4

123 1 2 0

124 1 3 1

125 2 4 99

126 3 4 99

127 */
View Code

 

你可能感兴趣的:(最短路)