hdu 2983
唉,这明明也是一道差不多的题目,为什么构图完之后,还是错了很久,我很不解呀,一直改,一直改,但是时间还是很慢,2766ms,SPFA+队列实现
所以很想改一下,用栈来实现,可结果却是给了我一个TLE,无语呀,不知道怎么回事,看了大牛的很快呀,差不多500ms,用SPFA+栈实现,难道是我在预处理,构图的时候,慢了?
不解呀?我自己的加边操作很方便,可是很慢吗?= =!
郁闷,看来得改改习惯了
额,都没讲下题目:
分析题意:
输入有两种形式:
1:P A B X 即 B + X = A 转化一下: B - A <= -X, A - B <= X 构造边和权:(A, B, -X), (B, A, X)
2:V A B 即 B +1<= A 转化一下:B - A <= -1 构造边和权:(A, B, -1)
先贴下我这个比较水,比较慢的代码
#include<iostream> #include<string> #include<queue> #define MAXINT 9999999 #define MAXN 1100 using namespace std; int dis[MAXN],n,m,num,p[MAXN]; int vis[MAXN],cou[MAXN]; queue<int> Q; struct edge { int v,w,next; edge(int _next=0,int _v=0,int _w=0):next(_next),v(_v),w(_w){}; }e[MAXN*201]; bool spfa() { for(int i=1;i<=n;i++) dis[i]=0; while(!Q.empty()) Q.pop(); for(int i=1;i<=n;i++) { Q.push(i); vis[i]=1; cou[i]=1; } while(!Q.empty()) { int t=Q.front(); Q.pop();vis[t]=0; for(int j=p[t];j!=-1;j=e[j].next) { if(dis[e[j].v]>e[j].w+dis[t]) { dis[e[j].v]=e[j].w+dis[t]; if(!vis[e[j].v]) { vis[e[j].v]=1; cou[e[j].v]++; if(cou[e[j].v]>n) return false; Q.push(e[j].v); } } } } return true; } int main() { char str; int a,b,c; while(cin>>n>>m) { num=0; memset(p,-1,sizeof(p)); for(int i=0;i<m;i++) { cin>>str; if(str=='P') { cin>>a>>b>>c; e[num]=edge(p[a],b,c); p[a]=num++; e[num]=edge(p[b],a,-c); p[b]=num++; } else { cin>>a>>b; e[num]=edge(p[b],a,-1); p[b]=num++; } } if(spfa()) cout<<"Reliable"<<endl; else cout<<"Unreliable"<<endl; } return 0; }
看下用栈实现的代码:
#include<stdio.h> #include<stdlib.h> #define INF 0xfffffff #define NN 1004 #define MM 200004 int edNum, N; int next[MM]; int root[NN]; int mark[NN]; int cnt[NN]; int dis[NN]; int stack[NN]; struct node{ int e, v; }edge[MM]; void add(int a, int b, int c){ edge[edNum].e = b; edge[edNum].v = c; next[edNum] = root[a]; root[a] = edNum++; } int Spfa() { int i, top, cur, tmp, nxt; top = 0; //初始化的时候没有加源点,直接将所有有根的点入栈,也很不错 for (i = 1; i <= N; i++){ dis[i] = INF; // key1 if (root[i] != -1){ stack[++top] = i; cnt[i]++; mark[i] = 1; } } while (top){ cur = stack[top--]; tmp = root[cur]; mark[cur] = 0; while (tmp != -1){ nxt = edge[tmp].e; //key2 if (dis[nxt] > dis[cur] + edge[tmp].v){ dis[nxt] = dis[cur] + edge[tmp].v; if (!mark[nxt]){ cnt[nxt]++; if (cnt[nxt] > N + 1){ return 1; } mark[nxt] = 1; stack[++top] = nxt; } } tmp = next[tmp]; } } return 0; } int main() { int i, a, b, c, M; char str[2]; while (scanf("%d%d", &N, &M) != EOF) { edNum = 0; for (i = 0; i <= N; i++){ root[i] = -1; mark[i] = 0; cnt[i] = 0; } while (M--){ scanf("%s%d%d", str, &a, &b); if (str[0] == 'P'){ scanf("%d", &c); add(b, a, c); add(a, b, -c); }else{ add(a, b, -1); } } if (Spfa()){ puts("Unreliable"); }else{ puts("Reliable"); } } return 0; }