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

 

posted @ 2015-05-27 20:30  鼠宝宝  阅读(219)  评论(0编辑  收藏  举报