Codeforces Round #287 (Div. 2) E. Breaking Good 最短路
题目链接:
http://codeforces.com/problemset/problem/507/E
E. Breaking Good
time limit per test2 secondsmemory limit per test256 megabytes
#### 问题描述
> Breaking Good is a new video game which a lot of gamers want to have. There is a certain level in the game that is really difficult even for experienced gamers.
>
> Walter William, the main character of the game, wants to join a gang called Los Hermanos (The Brothers). The gang controls the whole country which consists of n cities with m bidirectional roads connecting them. There is no road is connecting a city to itself and for any two cities there is at most one road between them. The country is connected, in the other words, it is possible to reach any city from any other city using the given roads.
>
> The roads aren't all working. There are some roads which need some more work to be performed to be completely functioning.
>
> The gang is going to rob a bank! The bank is located in city 1. As usual, the hardest part is to escape to their headquarters where the police can't get them. The gang's headquarters is in city n. To gain the gang's trust, Walter is in charge of this operation, so he came up with a smart plan.
>
> First of all the path which they are going to use on their way back from city 1 to their headquarters n must be as short as possible, since it is important to finish operation as fast as possible.
>
> Then, gang has to blow up all other roads in country that don't lay on this path, in order to prevent any police reinforcements. In case of non-working road, they don't have to blow up it as it is already malfunctional.
>
> If the chosen path has some roads that doesn't work they'll have to repair those roads before the operation.
>
> Walter discovered that there was a lot of paths that satisfied the condition of being shortest possible so he decided to choose among them a path that minimizes the total number of affected roads (both roads that have to be blown up and roads to be repaired).
>
> Can you help Walter complete his task and gain the gang's trust?
#### 输入
> The first line of input contains two integers n, m (2 ≤ n ≤ 105, ), the number of cities and number of roads respectively.
>
> In following m lines there are descriptions of roads. Each description consists of three integers x, y, z (1 ≤ x, y ≤ n, ) meaning that there is a road connecting cities number x and y. If z = 1, this road is working, otherwise it is not.
#### 输出
> In the first line output one integer k, the minimum possible number of roads affected by gang.
>
> In the following k lines output three integers describing roads that should be affected. Each line should contain three integers x, y, z (1 ≤ x, y ≤ n, ), cities connected by a road and the new state of a road. z = 1 indicates that the road between cities x and y should be repaired and z = 0 means that road should be blown up.
>
> You may output roads in any order. Each affected road should appear exactly once. You may output cities connected by a single road in any order. If you output a road, it's original state should be different from z.
>
> After performing all operations accroding to your plan, there should remain working only roads lying on some certain shortest past between city 1 and n.
>
> If there are multiple optimal answers output any.
> ####样例输入
> 8 9
> 1 2 0
> 8 3 0
> 2 3 1
> 1 4 1
> 8 7 0
> 1 5 1
> 4 6 1
> 5 7 0
> 6 8 0
样例输出
3
2 3 0
1 5 0
6 8 1
题意
给你n个点,m条边的图,每条边长度都为1,如果标记为0,则这条边待修,1则可正常使用,现在让你找一条最短路,路径上面的待修理的边最少。
题解
跑完最短路之后建最短路构成的DAG图,然后跑拓扑排序跑dp。
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf
typedef __int64 LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;
const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0);
//start----------------------------------------------------------------------
const int maxn=1e5+10;
struct Edge{
int u,v,z;
Edge(int u,int v,int z):u(u),v(v),z(z){}
};
struct Spfa{
int n,m;
vector<Edge> egs;
VI G[maxn],G2[maxn];
bool inq[maxn];
int d[maxn],d2[maxn];
void init(int n){
this->n=n;
for(int i=0;i<n;i++) G[i].clear();
egs.clear();
}
void addEdge(int u,int v,int z){
egs.pb(Edge(u,v,z));
m=egs.sz();
G[u].pb(m-1);
}
int spfa(int s,int *d){
queue<int> Q;
clr(inq,0);
rep(i,0,n) d[i]=INF;
d[s]=0,inq[s]=true,Q.push(s);
while(!Q.empty()){
int u=Q.front(); Q.pop();
inq[u]=false;
for(int i=0;i<G[u].sz();i++){
Edge& e=egs[G[u][i]];
if(d[e.v]>d[u]+1){
d[e.v]=d[u]+1;
if(!inq[e.v]){
Q.push(e.v);
inq[e.v]=true;
}
}
}
}
}
int ind[maxn],dp[maxn];
int pre[maxn];
bool vis[maxn*2];
void solve(){
clr(pre,-1);
clr(ind,0);
clr(vis,0);
clr(dp,0x3f);
spfa(0,d);
spfa(n-1,d2);
for(int i=0;i<m;i++){
Edge &e=egs[i];
if(d[e.u]+1+d2[e.v]==d[n-1]){
// prf("(%d,%d)\n",e.u+1,e.v+1);
G2[e.u].pb(i);
ind[e.v]++;
}
}
//
queue<int> Q;
Q.push(0),dp[0]=0;
while(!Q.empty()){
int u=Q.front(); Q.pop();
rep(i,0,G2[u].sz()){
Edge& e=egs[G2[u][i]];
if(dp[e.v]>dp[u]+(e.z^1)){
dp[e.v]=dp[u]+(e.z^1);
pre[e.v]=G2[u][i];
}
ind[e.v]--;
if(ind[e.v]==0){
Q.push(e.v);
}
}
}
// bug(dp[n-1]);
VI ans;
int p=n-1;
while(p){
Edge& e=egs[pre[p]];
// prf("<%d,%d>\n",e.u,e.v);
if(e.z==0){
ans.pb(pre[p]);
}
vis[pre[p]]=vis[pre[p]^1]=1;
p=e.u;
}
for(int i=0;i<m;i++){
if(vis[i]) continue;
Edge& e=egs[i];
if(e.z==1){
ans.pb(i);
}
vis[i]=vis[i^1]=1;
}
prf("%d\n",ans.sz());
rep(i,0,ans.sz()){
Edge& e=egs[ans[i]];
prf("%d %d %d\n",e.u+1,e.v+1,e.z^1);
}
}
}spfa;
int main() {
int n,m;
scf("%d%d",&n,&m);
spfa.init(n);
for(int i=0;i<m;i++){
int u,v,z;
scf("%d%d%d",&u,&v,&z); u--,v--;
spfa.addEdge(u,v,z);
spfa.addEdge(v,u,z);
}
spfa.solve();
return 0;
}
//end-----------------------------------------------------------------------
其实。。spfa跑最短路的时候就能处理出0最少的最短路径了。。orz..上面的做法好蠢。。
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf
typedef __int64 LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;
const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0);
//start----------------------------------------------------------------------
const int maxn=1e5+10;
struct Edge{
int u,v,z;
Edge(int u,int v,int z):u(u),v(v),z(z){}
};
struct Spfa{
int n,m;
vector<Edge> egs;
VI G[maxn];
bool inq[maxn];
int d[maxn],dp[maxn];
int pre[maxn];
void init(int n){
this->n=n;
for(int i=0;i<n;i++) G[i].clear();
egs.clear();
}
void addEdge(int u,int v,int z){
egs.pb(Edge(u,v,z));
m=egs.sz();
G[u].pb(m-1);
}
int spfa(int s){
clr(pre,-1);
clr(dp,0x3f);
queue<int> Q;
clr(inq,0);
rep(i,0,n) d[i]=INF;
dp[s]=0;
d[s]=0,inq[s]=true,Q.push(s);
while(!Q.empty()){
int u=Q.front(); Q.pop();
inq[u]=false;
for(int i=0;i<G[u].sz();i++){
Edge& e=egs[G[u][i]];
if(d[e.v]>d[u]+1||d[e.v]==d[u]+1&&dp[e.v]>dp[u]+(e.z^1)){
d[e.v]=d[u]+1;
dp[e.v]=dp[u]+(e.z^1);
pre[e.v]=G[u][i];
if(!inq[e.v]){
Q.push(e.v);
inq[e.v]=true;
}
}
}
}
}
bool vis[maxn*2];
void solve(){
clr(vis,0);
spfa(0);
VI ans;
int p=n-1;
while(p){
Edge& e=egs[pre[p]];
if(e.z==0){
ans.pb(pre[p]);
}
vis[pre[p]]=vis[pre[p]^1]=1;
p=e.u;
}
for(int i=0;i<m;i++){
if(vis[i]) continue;
Edge& e=egs[i];
if(e.z==1){
ans.pb(i);
}
vis[i]=vis[i^1]=1;
}
prf("%d\n",ans.sz());
rep(i,0,ans.sz()){
Edge& e=egs[ans[i]];
prf("%d %d %d\n",e.u+1,e.v+1,e.z^1);
}
}
}spfa;
int main() {
int n,m;
scf("%d%d",&n,&m);
spfa.init(n);
for(int i=0;i<m;i++){
int u,v,z;
scf("%d%d%d",&u,&v,&z); u--,v--;
spfa.addEdge(u,v,z);
spfa.addEdge(v,u,z);
}
spfa.solve();
return 0;
}
//end-----------------------------------------------------------------------
代码
Codeforces Round #287 (Div. 2) E. Breaking Good 最短路的更多相关文章
- Codeforces Round #287 (Div. 2) E. Breaking Good [Dijkstra 最短路 优先队列]
传送门 E. Breaking Good time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- Codeforces Round #287 (Div. 2) E. Breaking Good 路径记录!!!+最短路+堆优化
E. Breaking Good time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...
- 贪心 Codeforces Round #287 (Div. 2) A. Amr and Music
题目传送门 /* 贪心水题 */ #include <cstdio> #include <algorithm> #include <iostream> #inclu ...
- Codeforces Round #287 (Div. 2) C. Guess Your Way Out! 思路
C. Guess Your Way Out! time limit per test 1 second memory limit per test 256 megabytes input standa ...
- CodeForces Round #287 Div.2
A. Amr and Music (贪心) 水题,没能秒切,略尴尬. #include <cstdio> #include <algorithm> using namespac ...
- Codeforces Round #287 (Div. 2) C. Guess Your Way Out! 水题
C. Guess Your Way Out! time limit per test 1 second memory limit per test 256 megabytes input standa ...
- Codeforces Round #287 (Div. 2) B. Amr and Pins 水题
B. Amr and Pins time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...
- Codeforces Round #287 (Div. 2) A. Amr and Music 水题
A. Amr and Music time limit per test 1 second memory limit per test 256 megabytes input standard inp ...
- Codeforces Round #287 (Div. 2) D. The Maths Lecture [数位dp]
传送门 D. The Maths Lecture time limit per test 1 second memory limit per test 256 megabytes input stan ...
随机推荐
- 局域网,Internet,广域网
局域网:覆盖范围小,自己花钱买设备,带宽固定,自己单位维护 网线100米以内 带宽10m 100m 1000m Internet:ISP,自己的机房,对网民提供访问Internet连接 广域网:距离远 ...
- CAN总线的学习
CAN(controller Area Network )总线的学习 1986 年德国电气商博世公司开发出面向汽车的CAN 通信协议(数据之间的交互),其目的是为适应“减少线束的数量”.“通过多个LA ...
- 2017-2018-1 20155306 20155315 《信息安全技术》实验二、Windows口令破解
在网络界,攻击事件发生的频率越来越高,其中相当多的都是由于网站密码泄露的缘故,或是人为因素导致,或是口令遭到破解,所以从某种角度而言,密码的安全问题不仅仅是技术上的问题,更主要的是人的安全意识问题. ...
- Java线程和多线程(十三)——Callable,Future,FutureTask
在Java多线程之中,Callable和Future的使用时非常广泛的.在之前的文章中,我们了解了关于Java线程池基础的一些内容,知道如何提交Runnable的任务.但是,Runnable的任务是无 ...
- [BZOJ2961]共点圆-[凸包+cdq分治]
Description 传送门 Solution 考虑对于每一个点: 设圆的坐标为(x,y),点的坐标为(x0,y0).依题意得,当一个点在圆里,需要满足(x-x0)2+(y-y0)2<=x2+ ...
- 最优布线问题(wire.cpp)
最优布线问题(wire.cpp) [问题描述] 学校有n台计算机,为了方便数据传输,现要将它们用数据线连接起来.两台计算机被连接是指它们间有数据线连接.由于计算机所处的位置不同,因此不同的两台计算机的 ...
- tidb测试环境安装,离线部署
1.环境以及规划 机器:centos7.5 ; 文件系统为ext4:内存16g:cpu8核,共三个节点: ip hostname roles --- tidb tipd tikv --- tidb t ...
- 查看Oracle数据库表空间大小(空闲、已使用),是否要增加表空间的数据文件
查看Oracle数据库表空间大小(空闲.已使用),是否要增加表空间的数据文件 1.查看表空间已经使用的百分比 Sql代码 select a.tablespace_name,a.bytes/1024/1 ...
- device_create与device_register
//device_create的定义如下 struct device *device_create(struct class *class, struct device *parent, dev_t ...
- oracle 查看锁表及解锁的语句
解锁语句: alter system kill session 'sid, serial#'; alter system kill session '23, 1647'; 查询那些对象被锁: sele ...