Pizza Delivery
Pizza Delivery
时间限制: 2 Sec 内存限制: 128 MB
题目描述
Alyssa orders a piece of pizza everyday from the same pizzeria. The pizza is delivered along the shortest route from the intersection with the pizzeria to the intersection with Alyssa’s house.
Altering the traffic regulation may change the shortest route. Please tell Alyssa how the social experiment will affect the pizza delivery route.
输入
n m
a1 b1 c1
.
.
.
am bm cm
The first line contains two integers, n, the number of intersections, and m, the number of street sections in New Tsukuba City (2 ≤ n ≤ 100 000, 1 ≤ m ≤ 100 000). The intersections are numbered 1 through n and the street sections are numbered 1 through m.
The following m lines contain the information about the street sections, each with three integers ai, bi, and ci (1 ≤ ai ≤ n, 1 ≤ bi ≤ n, ai ≠ bi, 1 ≤ ci ≤ 100 000). They mean that the street section numbered i connects two intersections with the one-way direction from ai to bi, which will be reversed on the i-th day. The street section has the length of ci. Note that there may be more than one street section connecting the same pair of intersections.
The pizzeria is on the intersection 1 and Alyssa’s house is on the intersection 2. It is guaranteed that at least one route exists from the pizzeria to Alyssa’s before the social experiment starts.
输出
• HAPPY if the shortest route on the i-th day will become shorter,
• SOSO if the length of the shortest route on the i-th day will not change, and
• SAD if the shortest route on the i-th day will be longer or if there will be no route from the pizzeria to Alyssa’s house.
Alyssa doesn’t mind whether the delivery bike can go back to the pizzeria or not.
样例输入
4 5
1 3 5
3 4 6
4 2 7
2 1 18
2 3 12
样例输出
SAD
SAD
SAD
SOSO
HAPPY
来源/分类
题意:有向图中,翻转某一条边,问最短路径如何变化(变长,变短,不变)。
分析:设 d(u,v)代表从u到v的最短路,s为起点,t为终点。对于任一边(from,to),若d(s,to)+d(from,t)+value(from,to)< d(s,t),则翻转该边最短路减小。再求出所有最短路径所在的图,该图是DAG,若某一条边是DAG上的桥,则翻转该边后最短路径增大,否则不变。
证明参考:https://icpc.iisf.or.jp/2017-tsukuba/wp-content/uploads/sites/4/2017/12/commentaries2.pdf
做法:求最短路径的话正反跑两遍最短路就好了,让我感觉比较难的地方是求所有最短路径的DAG以及DAG上的桥。
求所有最短路径组成的DAG:对于任一条边(from,to),若d(s,from)+d(to,t)+value(from,to)== d(s,t),则该边是DAG上的边。
求DAG上的桥:第一种方法是把DAG上的有向边全部转化为无向边,然后用tarjan算法求无向图的桥。第二种方法是先统计出S到T的方案数,则有结论:如果这条边是桥边,那么这条边两边的点x、y也是必经点,而且s到x的方案数*y到t的方案数=s到t的方案数,这个是充分必要的。
tarjan求桥:
#include<bits/stdc++.h>
#define N 200050
using namespace std; typedef struct
{
int from,to,value,ori;
} ss; ss edg1[N],edg2[N];
vector<int>edges1[N];
int now_edges1=;
vector<int>edges2[N];
int now_edges2=; int is_bridge[N]= {};
long long dis1[N],dis2[N]; void spfa1()
{
for(int i=; i<N; i++)dis1[i]=LLONG_MAX/;
int vis[N]= {};
queue<int>q;
q.push();
vis[]=;
dis1[]=; while(!q.empty())
{
int now=q.front();
q.pop();
vis[now]=; int Size=edges1[now].size();
for(int i=; i<Size; i++)
{
ss e=edg1[edges1[now][i]];
if(dis1[e.to]>dis1[now]+e.value)
{
dis1[e.to]=dis1[now]+e.value; if(!vis[e.to])
{
q.push(e.to);
vis[e.to]=;
}
}
}
}
} void spfa2()
{
for(int i=; i<N; i++)dis2[i]=LLONG_MAX/;
int vis[N]= {};
queue<int>q;
q.push();
vis[]=;
dis2[]=; while(!q.empty())
{
int now=q.front();
q.pop();
vis[now]=; int Size=edges2[now].size();
for(int i=; i<Size; i++)
{
ss e=edg2[edges2[now][i]];
if(dis2[e.to]>dis2[now]+e.value)
{
dis2[e.to]=dis2[now]+e.value; if(!vis[e.to])
{
q.push(e.to);
vis[e.to]=;
}
}
}
}
} int dfn[N]= {},low[N]= {},now_clo=; void tarjan(int x,int pre)
{
dfn[x]=low[x]=now_clo++;
int Size=edges2[x].size(); for(int i=; i<Size; i++)
{
ss e=edg2[edges2[x][i]]; if(e.to!=pre)
{
if(!dfn[e.to])
{
tarjan(e.to,x);
low[x]=min(low[x],low[e.to]); if(low[e.to]>dfn[x])
{
is_bridge[e.ori]=;
} }
else
{
low[x]=min(low[x],dfn[e.to]);
}
}
}
} int main()
{
int n,m;
scanf("%d %d",&n,&m); for(int i=; i<=m; i++)
{
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
edges1[u].push_back(now_edges1);
edg1[now_edges1++]=(ss){u,v,w,i};
edges2[v].push_back(now_edges2);
edg2[now_edges2++]=(ss){v,u,w,i};
} spfa1();
spfa2(); long long bestedge=dis1[]; for(int i=; i<N; i++)edges2[i].clear();
now_edges2=; for(int i=; i<=n; i++)
{
int Size=edges1[i].size();
for(int j=; j<Size; j++)
{
int u=i,v=edg1[edges1[i][j]].to,w=edg1[edges1[i][j]].value,ori=edg1[edges1[i][j]].ori; if(dis1[u]+dis2[v]+w==bestedge)
{
edges2[u].push_back(now_edges2);
edg2[now_edges2++]=(ss){u,v,,ori};
edges2[v].push_back(now_edges2);
edg2[now_edges2++]=(ss){v,u,,ori};
}
}
} tarjan(,-); int ans[N]= {};
for(int i=; i<=n; i++)
{
int Size=edges1[i].size();
for(int j=; j<Size; j++)
{
int u=i,v=edg1[edges1[i][j]].to,w=edg1[edges1[i][j]].value,ori=edg1[edges1[i][j]].ori; if(dis1[v]+dis2[u]+w<bestedge)ans[ori]=;
else if(is_bridge[ori])ans[ori]=-;
}
} for(int i=; i<=m; i++)
if(ans[i]==)printf("HAPPY\n");
else if(ans[i]==-)printf("SAD\n");
else
printf("SOSO\n");
return ; }
统计路径数求桥:
#include<bits/stdc++.h>
#define N 200050
using namespace std; typedef struct
{
int from,to,value,ori;
} ss; ss edg1[N],edg2[N];
vector<int>edges1[N];
int now_edges1=;
vector<int>edges2[N];
int now_edges2=; int is_in_dag[N]= {};
long long dis1[N],dis2[N]; void spfa1()
{
for(int i=; i<N; i++)dis1[i]=LLONG_MAX/;
int vis[N]= {};
queue<int>q;
q.push();
vis[]=;
dis1[]=; while(!q.empty())
{
int now=q.front();
q.pop();
vis[now]=; int Size=edges1[now].size();
for(int i=; i<Size; i++)
{
ss e=edg1[edges1[now][i]];
if(dis1[e.to]>dis1[now]+e.value)
{
dis1[e.to]=dis1[now]+e.value; if(!vis[e.to])
{
q.push(e.to);
vis[e.to]=;
}
}
}
}
} void spfa2()
{
for(int i=; i<N; i++)dis2[i]=LLONG_MAX/;
int vis[N]= {};
queue<int>q;
q.push();
vis[]=;
dis2[]=; while(!q.empty())
{
int now=q.front();
q.pop();
vis[now]=; int Size=edges2[now].size();
for(int i=; i<Size; i++)
{
ss e=edg2[edges2[now][i]];
if(dis2[e.to]>dis2[now]+e.value)
{
dis2[e.to]=dis2[now]+e.value; if(!vis[e.to])
{
q.push(e.to);
vis[e.to]=;
}
}
}
}
} ss edg3[N],edg4[N];
vector<int>edges3[N];
int now_edges3=;
vector<int>edges4[N];
int now_edges4=; long long num_ways_1[N]={},num_ways_2[N]={};
const long long mod=1e9+; long long dfs1(int x)
{
if(num_ways_1[x])return num_ways_1[x]; long long sum=;
int Size=edges3[x].size();
for(int i=;i<Size;i++)
{
int to=edg3[edges3[x][i]].to;
sum=(sum+dfs1(to))%mod;
} return num_ways_1[x]=sum; } long long dfs2(int x)
{
if(num_ways_2[x])return num_ways_2[x]; long long sum=;
int Size=edges4[x].size();
for(int i=;i<Size;i++)
{
int to=edg4[edges4[x][i]].to;
sum=(sum+dfs2(to))%mod;
} return num_ways_2[x]=sum;
} int main()
{ int n,m;
scanf("%d %d",&n,&m); for(int i=; i<=m; i++)
{
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
edges1[u].push_back(now_edges1);
edg1[now_edges1++]=(ss){u,v,w,i};
edges2[v].push_back(now_edges2);
edg2[now_edges2++]=(ss){v,u,w,i};
} spfa1();
spfa2(); long long bestedge=dis1[]; for(int i=; i<=n; i++)
{
int Size=edges1[i].size();
for(int j=; j<Size; j++)
{
int u=i,v=edg1[edges1[i][j]].to,w=edg1[edges1[i][j]].value,ori=edg1[edges1[i][j]].ori; if(dis1[u]+dis2[v]+w==bestedge)
{
is_in_dag[ori]=; edges3[u].push_back(now_edges3);
edg3[now_edges3++]=(ss){u,v,,ori};
edges4[v].push_back(now_edges4);
edg4[now_edges4++]=(ss){v,u,,ori};
}
}
} num_ways_1[]=;
num_ways_2[]=; int ans[N]={};
for(int i=;i<=n;i++)
{
int Size=edges1[i].size();
for(int j=;j<Size;j++)
{
int u=i,v=edg1[edges1[i][j]].to,w=edg1[edges1[i][j]].value,ori=edg1[edges1[i][j]].ori; if(!is_in_dag[ori]&&dis1[v]+dis2[u]+w<bestedge)ans[ori]=;
else
if(is_in_dag[ori]&&dfs1(v)*dfs2(u)%mod==dfs1())ans[ori]=-;
}
} for(int i=;i<=m;i++)
if(ans[i]==)printf("HAPPY\n");
else
if(ans[i]==-)printf("SAD\n");
else
printf("SOSO\n");
return ; }
Pizza Delivery的更多相关文章
- 【暑假】[深入动态规划]UVa 1628 Pizza Delivery
UVa 1628 Pizza Delivery 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=51189 思路: ...
- uva1628 Pizza Delivery
fixing great wall 的变形dp(i,j,k,p)不考虑i-j的客人,还要送k个人,目前位置在p起点i和总数量k都要枚举dp(i,j,k,p)=max(dp(m,j,k-1,p)+val ...
- UVa1628 UVaLive5847 Pizza Delivery
填坑系列(p.302) 既然不知道后面还要卖多少个就加一维状态嘛.. lrj写的O(n)转移?其实转移可以O(1) 貌似按x排序有奇效? #include<cstdio> #include ...
- Aizu - 1383 Pizza Delivery (最短路图+DAG上的割边)
题意:给出一张有向图,每条边有长度,对于每条边,你要回答将该边的方向取反后,从起点到终点的最短距离是增加or减小or不变. 首先求出起点到所有点的最短距离和所有点到终点的最短距离(两次DIjkstra ...
- (好题)2017-2018 ACM-ICPC, Asia Tsukuba Regional Contest F Pizza Delivery
题意:给n个点m条边的有向图.每次使一条边反向,问你1到2的最短路变短,变长,还是不变. 解法:遇到这种题容易想到正向求一遍最短路d1,反向再求一遍最短路d2.纪录原图上的最短路为ans,然后分开考虑 ...
- [GodLove]Wine93 Tarining Round #1
比赛链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=44664#overview 题目来源: 2011 Asia Regional ...
- CodeForces 151B Phone Numbers
Phone Numbers Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Sub ...
- Asia-Tsukuba 2017
A. Secret of Chocolate Poles DP,$f[i][j]$表示高度为$i$,顶层颜色为$j$的方案数. 时间复杂度$O(l)$. #include<cstdio> ...
- 2017-2018 ACM-ICPC, Asia Tsukuba Regional Contest
2017-2018 ACM-ICPC, Asia Tsukuba Regional Contest A Secret of Chocolate Poles 思路:暴力枚举黑巧克力的个数和厚黑巧克力的个 ...
随机推荐
- HDU 1171 Big Event in HDU 杭电大事件(母函数,有限物品)
题意: 分家问题,对每种家具都估个值,给出同样价值的家具有多少个,要求尽可能平分,打印的第一个数要大于等于第二个数. 思路: 可以用背包做,也可以用母函数.母函数的实现只需要注意一个点,就是每次以一种 ...
- (1)Ngixn 编译安装 (版本:1.12.1)
1.创建用户和群组 groupadd nginx 创建一个用户,不允许登陆和不创主目录 useradd -s /sbin/nologin -g nginx -M ngi ...
- CentOS 7.0关闭防火墙
.关闭firewall: systemctl stop firewalld.service #停止firewall systemctl disable firewalld.service #禁止fir ...
- kubernetes添加不了google apt-key
转自icepoint的博客 key来源 我的百度云盘 密码:v3wo 下载kube_apt_key.gpg到本地,上传到服务器后执行下面的命令 apt-get update && ap ...
- Oracle旗下软件官网下载速度过慢解决办法
平常下载Oracle旗下软件官网的产品资源,会发现速度很慢,如下载JDK和mysql时, 这样很浪费我们的时间 解决办法: 复制自己需要下载的资源链接 使用迅雷下载该资源 速度均很快 如下载Mysql ...
- Bootstrap历练实例:基本输入框组
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- 使用xcode workspace 多个project协同工作
一般的某个应用单独新建一个 project 就可以了,然后把所有的程序文件都放在里面,这个可以满足大部分普通的需求,但是有时候,项目有可能要使用其他的项目文件,或者引入其他的静态库文件,这个时候 wo ...
- C# Excel常用控件总结
参考:https://blog.csdn.net/waterstar50/article/details/80590355 1.ClosedXML2.EPPlus 教程:http://www.cnbl ...
- css去除链接 input 虚框
/* css去掉虚框 */ :focus{-webkit-outline-style:none;-moz-outline-style:none;-ms-outline-style:none;-o-ou ...
- 基于ubuntu 14.04 kvm虚拟化部署
1. 宿主机环境(dell备份服务器) Ubuntu 14.04 LTS 64位 内存:16G 硬盘:2T 2. 确认CPU是否支持硬件虚拟化 root@shwilling:~# egrep -o ' ...