Gym - 100765C King Berl VI 差分约束
2017-04-17 20:42
120 查看
这题和sgu298是一个题,但是在sgu上这个题是1.5s,在gym上是0.5s,就很坑。。。
题意可以看一下点击打开链接
查分约束,一般的做法是用spfa算法,但这题会TLE...各种乱改了好长时间,在vj上看了别人一个代码才明白
可以先用tarjan算法求强连通分量,如果一个点和他相邻的点在同一个强连通分量里,则无解
然后缩点,在用拓扑排序替代spfa求解
这样的复杂度只有O(e)
题意可以看一下点击打开链接
查分约束,一般的做法是用spfa算法,但这题会TLE...各种乱改了好长时间,在vj上看了别人一个代码才明白
可以先用tarjan算法求强连通分量,如果一个点和他相邻的点在同一个强连通分量里,则无解
然后缩点,在用拓扑排序替代spfa求解
这样的复杂度只有O(e)
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; const int maxn=10005; const int maxm=300005; int n,m; int headz[maxn],headf[maxn]; int tot,ord,scc,top,idx; int disz[maxn],disf[maxn]; int vis[maxn],inq[maxn]; int instack[maxn]; int DFN[maxn]; int low[maxn]; int st[maxn]; int block[maxn]; int head[maxn]; int que[maxn],que2[maxn]; int indeg[maxn],outdeg[maxn]; struct node { int v,next,dis; }edgez[maxm],edgef[maxm],edge[maxm]; void addedge(int u,int v,int d) { edgez[tot].v=v; edgez[tot].dis=d; edgez[tot].next=headz[u]; headz[u]=tot; edgef[tot].v=u; edgef[tot].dis=d; edgef[tot].next=headf[v]; headf[v]=tot++; } void add(int u,int v,int d) { edge[idx].v=v; edge[idx].dis=d; edge[idx].next=head[u]; head[u]=idx++; } void init() { memset(headz,-1,sizeof(headz)); memset(headf,-1,sizeof(headf)); memset(head,-1,sizeof(head)); tot=0; ord=0; scc=0; top=0; idx=0; } void tarjan(int u) { DFN[u]=low[u]=++ord; instack[st[++top]=u]=1; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].v; if(!DFN[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(instack[v]) low[u]=min(low[u],DFN[v]); } int v; if(DFN[u]==low[u]) { scc++; do { instack[v=st[top--]]=0; block[v]=scc; } while(v!=u); } } int check() { int u,v,d; scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { scanf("%d%d%d",&u,&v,&d); add(u,v,d); } for(int i=1;i<=n;i++) { if(!DFN[i]) tarjan(i); } for(int i=1;i<=n;i++) { for(int j=head[i];j!=-1;j=edge[j].next) { int v=edge[j].v; if(block[i]==block[v]&&edge[j].dis) return 0; else if(block[i]!=block[v]) { ++indeg[block[v]]; ++outdeg[block[i]]; addedge(block[i],block[v],edge[j].dis); } } } return 1; } int solve() { int front=0,rear=0,front2=0,rear2=0; for(int i=1;i<=scc;i++) { disz[i]=10000; disf[i]=-10000; if(!indeg[i]) que[++rear]=i; if(!outdeg[i]) que2[++rear2]=i; } while(front!=rear) { int t=que[++front]; for(int i=headz[t];i!=-1;i=edgez[i].next) { int v=edgez[i].v; --indeg[v]; disz[v]=min(disz[v],disz[t]-edgez[i].dis); if(!indeg[v]) que[++rear]=v; } } while(front2!=rear2) { int t=que2[++front2]; for(int i=headf[t];i!=-1;i=edgef[i].next) { int v=edgef[i].v; --outdeg[v]; disf[v]=max(disf[v],disf[t]+edgef[i].dis); if(!outdeg[v]) que2[++rear2]=v; } } for(int i=1;i<=scc;i++) { if(disz[i]<=disf[i]) return 0; } return 1; } void getans() { disz[block ]=disf[block ]; for(int i=1;i<=scc;i++) { for(int j=headz[que[i]];j!=-1;j=edgez[j].next) { disz[edgez[j].v]=min(disz[edgez[j].v],disz[que[i]]-edgez[j].dis); } } for(int i=1;i<n;i++) printf("%d ",disz[block[i]]); printf("%d\n",disz[block ]); } int main() { init(); if(!check()) printf("-1\n"); else if(!solve()) printf("-1\n"); else getans(); return 0; }
相关文章推荐
- Codeforces gym 2013-2014 Samara SAU ACM ICPC Quarterfinal Qualification Contest
- CodeForcesGym 100502E Opening Ceremony
- gym 100496 House of Representatives(树形dp)
- Codeforces Gym 2015 ACM Amman Collegiate Programming Contest
- Codeforces Gym 100513M M. Variable Shadowing 暴力
- Gym 100187M - Heaviside Function
- Gym 100703K Word order 简单贪心
- B - Lunch-Gym 100637B-找规律过的
- codeforce Gym 100342J Triatrip (bitset)
- Codeforces Gym H. Hell on the Markets 贪心
- Gym 100625A 间谍租车问题-简单模拟-(map的使用)
- Codeforces Gym 100523E E - Gophers SET
- Codeforces Gym 100203G G - Good elements 标记暴力
- Codeforces Gym 100650B Countdown (离线)
- Codeforces Gym 100338B Spam Filter 字符串哈希+贝叶斯公式
- CodeForcesGym 100641D Generalized Roman Numerals
- Gym - 100342I Travel Agency(割顶)
- Codeforces Gym 100002 C "Cricket Field" 暴力
- Codeforces Gym 100342F Move to Front 平衡树
- Gym 100685A Ariel (&运算)