CF round 314 E
来源:互联网 发布:麦可风淘宝购买 编辑:程序博客网 时间:2024/05/15 02:36
给一个有向图,现在要从1走最短路走到n,对于每条边问是否必须要经过这条边,如果不是再求能否保证边长大于0的前提下,减少这条边的权值使这条边必须被经过,并输出最小的减少的值。
我觉得这题意不难理解吧,就不多说了。首先当然是要跑一遍最短路啦,注意这题有数据卡SPFA,要写堆优化dijkstra才行。然后我们发现跑一遍还不够,还得以n为起点在反向边中再跑一遍最短路,这就求出了每个点p:从1到p的最短路d1[p]和从p到n的最短路d2[p]。
然后枚举所有的边(u,v),如果这条边是在最短路径上的话,那就满足d1[u]+w+d2[v]==d1[n],
对于找桥的问题,由于这个题的特殊性有个个人认为不错的方法,那就是把0..d1[n]看作一个区间,那么对于每条最短路边(u,v)来说,d1[u]..d1[v]表示一个子区间,那显然我们只要找出0..d1[n]上没有重叠的区间即可。
这里可以把所有最短路边离线处理出来,然后根据左端点从小到大排序,左端点相同则按右端点从大到小排序,然后乱搞一下就把桥都弄出来了。
那对于其余最短路边显然只要权值大于1的话减1就满足条件了。
对于其他边就显然使权值变为d1[n]-d1[u]-d2[v]-1就可以了,判断一下这个是不是大于0就好。再认真看看可以发现上一行的东西也满足这个,那就可以把非桥的边统一用这个判断了。
代码:
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#include<string>#include<iomanip>#pragma comment(linker, "/STACK:1024000000,1024000000")#include<vector>#include<set>#include<map>#include<queue>#include<list>using namespace std;typedef long long LL;typedef unsigned long long ULL;typedef pair<int,LL> mp;#define rep(i,k,n) for(int i=(k);i<=(n);i++)#define red(i,k,n) for(int i=(k);i>=(n);i--)#define sqr(x) ((x)*(x))#define clr(x,y) memset((x),(y),sizeof(x))#define mod 1000000007#define MAX(a,b) ((a)>(b)?(a):(b))#define MIN(a,b) ((a)>(b)?(b):(a))//const int maxn = ;int n,m,S,T;LL d[2][100010];bool ans[100010];struct edge{ int v,w,next;}e[2][100010];int ecnt=0,h[2][100010];struct line{ LL l,r; int id; bool operator < (const line &a){return l==a.l?r>a.r:l<a.l;}}p[100010];void addedge(int u,int v,int w){ ecnt++; e[1][ecnt].v=u; e[0][ecnt].v=v; e[1][ecnt].next=h[1][v]; e[0][ecnt].next=h[0][u]; e[0][ecnt].w=e[1][ecnt].w=w; h[1][v]=h[0][u]=ecnt;}void dijkstra(int s,int x){ priority_queue<mp,vector<mp>,greater<mp> > q; mp oq; d[x][s]=0; q.push(mp(0,s)); while(!q.empty()) { oq=q.top(); q.pop(); int i=oq.second; for(int j=h[x][i];~j;j=e[x][j].next) { int v=e[x][j].v; if(d[x][i]+e[x][j].w<d[x][v]) { d[x][v]=d[x][i]+e[x][j].w; q.push(mp(d[x][v],v)); } } }}int main(){//#define LOCAL#ifdef LOCALfreopen("e:\\read.txt","r",stdin);freopen("e:\\write.txt","w",stdout);#endif cin>>n>>m>>S>>T; clr(h,-1); clr(d,0x3f); rep(i,1,m) { int u,v,w; scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); } dijkstra(S,0); dijkstra(T,1); clr(ans,0); int cnt=0; rep(i,1,m) { int v=e[0][i].v; int u=e[1][i].v; if(d[0][u]+e[0][i].w+d[1][v]==d[0][T]) { p[++cnt].l=d[0][u]; p[cnt].r=d[0][v]-1; p[cnt].id=i; } } sort(p+1,p+1+cnt); for(int i=1;i<=cnt;) { int j=i+1; LL maxr=p[i].r; while(p[j].l<=maxr&&j<=cnt) { maxr=MAX(maxr,p[j].r); j++; } if(j==i+1)ans[p[i].id]=1; i=j; } rep(i,1,m) { int v=e[0][i].v; int u=e[1][i].v; if(ans[i])puts("YES"); else { if(d[0][T]-d[0][u]-d[1][v]-1>0)printf("CAN %I64d\n",e[0][i].w-(d[0][T]-d[0][u]-d[1][v]-1)); else puts("NO"); } }return 0;}
做完这题才会用优先队列这个神器,妈妈我再也不手写堆了= =
0 0
- CF round 314 E
- CF Round #254 (Div. 2) E
- CF Round 418(div2) E题解
- cf Educational Codeforces Round 25 E
- Cf Round #104 (Div. 1) E Lucky Queries 线段树
- cf Round #280 (Div. 2) E. Vanya and Field 数学
- CF Round#324 (Div2) E. Anton and Ira
- CF Educational Codeforces Round 6 E题 dfs+线段树
- cf round 384 div2 E,二分 + 状压DP
- cf Educational Codeforces Round 20 E. Roma and Poker
- CF-Codeforces Round #420 (Div. 2) A ~ E
- cf Educational Codeforces Round 26 E. Vasya's Function
- cf-e
- E. President and Roads (CF Round #Pi (Div. 2)) 优先队列的Dij+Tarjan找桥
- cf/Codeforces Round #371 714E - Sonya and Problem Wihtout a Legend - dp +lis
- CF Round#409 Div2 E题DAG最长路+求解线性同余方程以后补
- CF round#420 div.2 E Okabe and El Psy Kongroo【矩阵快速幂】
- CF-Codeforces Round #420 (Div. 2)-E-Okabe and El Psy Kongroo
- 带有进度显示的文件拷贝模块
- python将对象写入文件,以及从文件中读取对象
- 夜深的窗,星空的床,外星的女人,想象的放荡,逻辑的流氓,懒了,忘了,跑了。。。
- 1035. 插入与归并(25)
- 泛型委托 Predicate/Func/Action
- CF round 314 E
- MySQL学习----MySQL函数(二)----12MySQL数据加密函数
- C++中虚函数与纯虚函数以及虚继承的相关知识
- getCacheDir()、getFilesDir()、getExternalFilesDir()、getExternalCacheDir()区
- 设计模式系列
- MySQL学习----MySQL函数(二)----13MySQL控制流函数
- Android Api Demos登顶之路(六十)Content-->ClipBoard
- 日本語 擬態語#2 かさかさ てかてか もちもち ふにゃふにゃ
- 链接