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 思路:暴力枚举黑巧克力的个数和厚黑巧克力的个 ...
随机推荐
- 【iOS】UITableview cell 顶部空白的n种设置方法
我知道没人会主动设置这个东西,但是大家一定都遇到过这个问题,下面总结下可能是哪些情况: 1, self.automaticallyAdjustsScrollViewInsets = NO; 这个应该 ...
- (十三)maven之release和snapshots
发布release 用户A将代码打包到RELEASE仓库.用户B使用时,需要在pom.xml添加jar包的依赖坐标.如果用户A将jar包版本从1.0升级到2.0,用户B使用时也需要在pom.xml中修 ...
- Android串口通信
前段时间因为工作需要研究了一下android的串口通信,网上有很多讲串口通信的文章,我在做的时候也参考了很多文章,现在就将我学习过程中的一些心得分享给大家,希望可以帮助大家在学习的时候少走一些弯路,有 ...
- JAVASCRIPT闭包以及原型链
方法内部还有个方法,实例化父方法后,再次调用父方法,可以运行父方法内部的子方法,这样的程序就叫做闭包 DEMO如下: //function outerFn() { // var outerVar = ...
- webpack之postcss集成
项目 为了 兼容各个浏览器,需要加各种 c3前缀,如果手动的加肯定 相对比较麻烦,但是现在有webpack,gulp之类的 工具可以自动给我们加上,可以说效率上加速不少.如果 配置中 做个happyp ...
- java运行环境jdk的安装和环境变量的配置教程
jdk的下载与安装 一.官网下载jdk 1.百度搜索jdk,进入官网,如下图所示: 官网下载jdk图1 2.在官网网站中找到合适的版本下载(以最新版本为例),如下图所示: 官网下载jdk图2 官网下载 ...
- PAT (Advanced Level) Practise - 1096. Consecutive Factors (20)
http://www.patest.cn/contests/pat-a-practise/1096 Among all the factors of a positive integer N, the ...
- 不安装oracle客户端用sqlplus连接数据库
在不安装oracle客户端情况下用sqlplus连接数据库: 1.去官网下载 http://www.oracle.com/technetwork/topics/winx64soft-089540.ht ...
- sscanf的使用
sscanf的使用 语法 int ssanf(const char *buffer, const char *format,[argument]...); 参数 buffer 存储的数据 format ...
- __new__.py
def func(self): print('hello %s' %self.name)def __init__(self,name,age): self.name = name self.age = ...