题目大意:有一个无向图,其中N个点,M条边,修改其中边权为0的所有边,使得他们的权值在1到1E18之间且从S到T的最短路的距离是L,请问是否存在修改方案,存在打出修改后所有边权的权值。
分析:如果直接暴力,显然1E18的复杂度会TLE,所以无脑二分,我们先判断如果边权为0的边,去掉后最短路的值,若这个值小于L显然是不存在的,若这个值等于L边权为0的边直接赋值1E18就行,之后将边权为0的边赋值为1,在跑一次最短路,因为经过了前两次的判断,那么,这个最短路肯定会经过原来0的边,赋值1后,逐条边进行调控就行,确保每次调控后的最短路小于等于L就行
具体步骤如下:
1.不将不知道长度的边跳过,求最短路,若最短路小于L则一定不可能成功输出NO,若等于则将未知边长设定为INF若大于则执行2
2.将所有未知边都设成1,跑最短路,若最短路大于L则一定不能成功(因为题意规定边长最小为1)输出NO,否则执行第3步
3.首先在第二步中回溯一遍最短路,将经过的未知边打上标记。对于未打上标记的未知边设值为INF,其他值为1,然后依次枚举这些点二分这些点的答案,跑最短路。(每次确定一点答案后再跑一遍最短路,若最短路为L则推出枚举)
//AC代码:
#include<vector>
#include<queue>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const ll maxn = 1100;
const ll N = 1e4 + 10;
const ll inf = 4e18 + 10;
const ll INF = 1e9 + 10;
struct edge{
ll to;
ll w;
}tex;
struct node{
ll to;
ll len;
bool operator < (const node & fx) const{
return len > fx.len;
}
}tey;
vector<struct edge>ver[maxn];
ll dis[maxn];
int vis[maxn];
int isin[maxn];
int isin2[maxn];
ll pre[maxn];
void dijkstra(ll s){
priority_queue<struct node>q;
fill(dis, dis + maxn, inf);
memset(vis, 0, sizeof(vis));
fill(pre, pre + maxn, -1);
dis[s] = 0;
tey.to = s;
tey.len = 0;
q.push(tey);
while(!q.empty()){
ll u = q.top().to;
q.pop();
if(vis[u] == 1) continue;
vis[u] = 1;
for(int i = 0; i < ver[u].size(); i++){
if(dis[u] + ver[u][i].w < dis[ver[u][i].to]){
dis[ver[u][i].to] = dis[u] + ver[u][i].w;
tey.to = ver[u][i].to;
tey.len = dis[ver[u][i].to];
q.push(tey);
pre[ver[u][i].to] = u;
}
}
}
}
vector<ll> xt, yt, stx, sty;
vector<int>xz, yz, sxz, syz;
vector<ll>NG;
ll id[maxn][maxn];
int main(){
memset(isin, 0, sizeof(isin));
memset(isin2, 0, sizeof(isin2));
ll n, m, s, t, bl; ll u[N], v[N], w[N];
cin>>n>>m>>bl>>s>>t; int cnt = 0;
for(ll i = 1; i <= m; i++){
cin>>u[i]>>v[i]>>w[i];
id[u[i]][v[i]] = id[v[i]][u[i]] = i;
tex.to = v[i]; tex.w = w[i];
ver[u[i]].push_back(tex);
tex.to = u[i];
ver[v[i]].push_back(tex);
if(w[i] == 0){
isin[u[i]] = 1; isin[v[i]] = 1;
xt.push_back(u[i]);
yt.push_back(v[i]);
xz.push_back(ver[u[i]].size() - 1);
yz.push_back(ver[v[i]].size() - 1);
NG.push_back(i);
//cnt++;
}
}
for(int i = 0; i < xt.size(); i++){
ver[xt[i]][xz[i]].w = inf;
}
for(int i = 0; i < yt.size(); i++){
ver[yt[i]][yz[i]].w = inf;
}
dijkstra(s);
if(dis[t] < bl){
cout<<"NO\n";
return 0;
}else if(dis[t] == bl){
cout<<"YES\n";
for(int i = 0; i < NG.size(); i++){
w[NG[i]] = 1e18;
}
for(ll i = 1; i <= m; i++){
cout<<u[i]<<" "<<v[i]<<" "<<w[i]<<endl;
}
return 0;
}
for(int i = 0; i < xt.size(); i++){
ver[xt[i]][xz[i]].w = 1;
}
for(int i = 0; i < yt.size(); i++){
ver[yt[i]][yz[i]].w = 1;
}
dijkstra(s);
if(dis[t] > bl){
cout<<"NO\n";
return 0;
}else if(dis[t] == bl){
cout<<"YES\n";
for(int i = 0; i < NG.size(); i++){
w[NG[i]] = 1;
}
for(ll i = 1; i <= m; i++){
cout<<u[i]<<" "<<v[i]<<" "<<w[i]<<endl;
}
return 0;
}
ll rt = t;
while(rt != -1){
if(pre[rt] != -1){
if(isin[rt] && isin[pre[rt]]){
isin2[rt] = 1;
isin2[pre[rt]] = 1;
}
}
rt = pre[rt];
}
for(int i = 0; i < xt.size(); i++){
ll go = ver[xt[i]][xz[i]].to;
if(isin2[go] && isin2[xt[i]]){
ver[xt[i]][xz[i]].w = 1;
w[id[xt[i]][go]] = 1;
stx.push_back(xt[i]);
sxz.push_back(xz[i]);
cnt++;
}else{
ver[xt[i]][xz[i]].w = INF;
w[id[xt[i]][go]] = INF;
}
}
for(int i = 0; i < yt.size(); i++){
ll go = ver[yt[i]][yz[i]].to;
if(isin2[go] && isin2[yt[i]]){
ver[yt[i]][yz[i]].w = 1;
w[id[yt[i]][go]] = 1;
sty.push_back(yt[i]);
syz.push_back(yz[i]);
}else{
ver[yt[i]][yz[i]].w = INF;
w[id[yt[i]][go]] = INF;
}
}
//ll ans = -1;
for(int i = 0; i < cnt; i++){
ll l = 0;
ll r = 1e18;
while(l <= r){
ll mid = (l + r)>>1;
ver[stx[i]][sxz[i]].w = mid;
ver[sty[i]][syz[i]].w = mid;
dijkstra(s);
if(dis[t] > bl) r = mid - 1;
else l = mid + 1;
}
ver[stx[i]][sxz[i]].w = r;
ver[sty[i]][syz[i]].w = r;
w[id[stx[i]][sty[i]]] = r;
dijkstra(s);
if(dis[t] == bl) break;
}
cout<<"YES\n";
for(ll i = 1; i <= m; i++){
cout<<u[i]<<" "<<v[i]<<" "<<w[i]<<endl;
}
return 0;
}