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 思路:暴力枚举黑巧克力的个数和厚黑巧克力的个 ...
随机推荐
- 洛谷 P1309 瑞士轮
题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公平,偶然性较低,但比赛过程往往十分 ...
- python暴力破解wifi密码程序
import time # 破解wifi库 import pywifi from pywifi import const class PoJie(object): def __init__(self, ...
- shell脚本,编程题练习。
题目是:将 文件file为 b+b+b+b+b+b+b+b 变为 b+b=b+b=b+b=b+b 解答方法如下:
- 蓝牙学习 (7) - raspberrryPi 扫描TI sensorTag
前面几篇分别简单涉及了 raspberryPi上bluez BLE sniffer TI SensorTag https://blog.csdn.net/feiwatson/article/detai ...
- python上的数据库sqlite3——插入多行数据
学校课程上的一个知识点,一个简单的课后习题:一劳永逸实现多行数据的插入(应该是这个意思,老师也没讲清楚).直接上代码了没啥好讲的,我感觉这个思路好捞. import sqlite3 con = sql ...
- MPEG-4视频编码核心思想
1 引言 当今时代,信息技术和计算机互联网飞速发展,在此背景下,多媒体信息已成为人类获取信息的最主要载体,同时也成为电子信息领域技术开发和研究的热点.多媒体信息经数字化处理后具有易于加密.抗干扰能 ...
- SpringSecurity结合数据库表实现权限认证
SpringSecurity结合数据表实现权限认证: 下面的案例是在SpringBoot框架实现的: 步骤一:准备数据库表 以下是五张表的脚本 ### 用户表 create table Sys_Use ...
- centos 服务器配置
安装防火墙 安装Apache 安装MySQL 安装PHP 安装JDK 安装Tomcat 服务器上搭建Apache +MySQL+PHP +JDK +Tomcat环境,用的是Linux Centos7. ...
- 03004_Web开发
1.Web开发中常见的概念 (1)B/S系统和C/S系统 ①Brower/Server:浏览器 服务器 系统------网站: ②Client/Server:客户端 服务器 系统------QQ.大型 ...
- 【21】外边距折叠(collapsing margins)
[21]外边距折叠(collapsing margins) 外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距. 合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者. [注意]m ...