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 思路:暴力枚举黑巧克力的个数和厚黑巧克力的个 ...
随机推荐
- 微软OneDrive使用体验
OneDrive是微软推出的一款软件,提供类似百度网盘的功能,能够在线存储照片和文档, 号称从任意电脑.Mac 电脑或手机都可访问. 一起来看看吧,第一次用之前需要进行简单配置. 因为是一个同步盘,需 ...
- pytest生成测试报告
生成JunitXML格式的测试报告 --junitxml=report\h.xml 生成result log 格式的测试报告 --resultlog=report\h.log 生成htm ...
- 理解 React,但不理解 Redux,该如何通俗易懂的理解 Redux?(转)
作者:Wang Namelos 链接:https://www.zhihu.com/question/41312576/answer/90782136来源:知乎 解答这个问题并不困难:唯一的要求是你熟悉 ...
- 同时使用多个UITableView
1.xib\storyboard中给2个tableView设置constraints(等宽) 方法 : ①设置mainTableView的上\下\左\三部分的约束为0:subTableView上\下\ ...
- 初涉「带权并查集」&&bzoj3376: [Usaco2004 Open]Cube Stacking 方块游戏
算是挺基础的东西 Description 约翰和贝茜在玩一个方块游戏.编号为1到n的n(1≤n≤30000)个方块正放在地上.每个构成一个立方柱. 游戏开始后,约翰会给贝茜发出P(1≤P ...
- 条款40:明智而审慎地使用多重继承(use multiple inheritance judiciously)
NOTE: 1.多重继承比单一继承复杂.它可能导致新的歧义性,以及对virtual继承的需要. 2.virtual 继承会增加大小 速度 初始化(及赋值)复杂度等等成本.如果virtual base ...
- nw335 debian sid x86-64 -- 6 第三方驱动
nw335 debian sid x86-64 -- 6 第三方驱动
- 文本搜索grep知识点总结
文本搜索工具:grep, egrep 根据用户指定的模式对目标文件进行过滤,显示被模式匹配到的行 grep [OPTION]... 'PATTERN' FILE... ...
- 电脑连接到手机并安装手机驱动usb-driver
设置真机开发环境需要执行下面几个步骤: 1.在应用的Manifest文件中声明应用是可调试的: 2.打开应用的调试支持: 对于通过Eclipse创建的应用,可以省略步骤2,因为在Eclipse IDE ...
- UVa 11987 并查集 Almost Union-Find
原文戳这 与以往的并查集不同,这次需要一个删除操作.如果是叶子节点还好,直接修改父亲指针就好. 但是如果要是移动根节点,指向它的所有子节点也会跟着变化. 所以要增加一个永远不会被修改的虚拟根节点,这样 ...