Complete The Graph CodeForces - 716D 最短路+暴力 很好的一道题

ZS the Coder has drawn an undirected graph of n vertices numbered from 0 to n - 1 and m edges between them. Each edge of the graph is weighted, each weight is a positive integer.

The next day, ZS the Coder realized that some of the weights were erased! So he wants to reassign positive integer weight to each of the edges which weights were erased, so that the length of the shortest path between vertices s and t in the resulting graph is exactly L. Can you help him?

Input

The first line contains five integers n, m, L, s, t (2 ≤ n ≤ 1000,  1 ≤ m ≤ 10 000,  1 ≤ L ≤ 109,  0 ≤ s, t ≤ n - 1,  s ≠ t) — the number of vertices, number of edges, the desired length of shortest path, starting vertex and ending vertex respectively.

Then, m lines describing the edges of the graph follow. i-th of them contains three integers, ui, vi, wi (0 ≤ ui, vi ≤ n - 1,  ui ≠ vi,  0 ≤ wi ≤ 109). ui and vi denote the endpoints of the edge and wi denotes its weight. If wi is equal to 0 then the weight of the corresponding edge was erased.

It is guaranteed that there is at most one edge between any pair of vertices.

Output

Print "NO" (without quotes) in the only line if it's not possible to assign the weights in a required way.

Otherwise, print "YES" in the first line. Next m lines should contain the edges of the resulting graph, with weights assigned to edges which weights were erased. i-th of them should contain three integers uivi and wi, denoting an edge between vertices ui and vi of weight wi. The edges of the new graph must coincide with the ones in the graph from the input. The weights that were not erased must remain unchanged whereas the new weights can be any positive integer not exceeding 1018.

The order of the edges in the output doesn't matter. The length of the shortest path between s and t must be equal to L.

If there are multiple solutions, print any of them.

Example
Input
5 5 13 0 4
0 1 5
2 1 2
3 2 3
1 4 0
4 3 4
Output
YES
0 1 5
2 1 2
3 2 3
1 4 8
4 3 4
Input
2 1 123456789 0 1
0 1 0
Output
YES
0 1 123456789
Input
2 1 999999999 1 0
0 1 1000000000
Output
NO
Note

Here's how the graph in the first sample case looks like :

In the first sample case, there is only one missing edge weight. Placing the weight of 8 gives a shortest path from 0 to 4 of length 13.

In the second sample case, there is only a single edge. Clearly, the only way is to replace the missing weight with 123456789.

In the last sample case, there is no weights to assign but the length of the shortest path doesn't match the required value, so the answer is "NO".





做法:

一开始把所有的0边先标记好,之后把0变为无穷大来计算最短路。

当所有的未知边都是无穷大的时候,我们的最短路还是小了,那么我们是无解的,我们没办法更大了。

如果正好等于,那么我们直接输出即可。

如果大于,说明我们有些未知边不能设置为无穷大。那么应该设为什么呢,我们暴力枚举。

我们暴力枚举每一条未知边,把某条边设为1,再求最短路。如果当前的最短路还是大了,那么我们继续变下一条边为1.

如果等于,那么直接输出。如果小于,计算出小了多少。那么我们就应该把刚刚更改为1的那条边加上小于的数值即可。


这道题有个迷之超时....记录未知边时放到if里就超时,不放就不超时...无奈..

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<vector>
#define inf 0x7f7f7f
using namespace std;
const int maxn = 1e5+10;
struct node
{
    int u;
    int to;
    int next;
    long long cost;
} edge[maxn<<1];
int head[maxn],tot;
int n,m,s,t;
long long path[maxn];
bool vis[maxn];


vector<int> kongbai;
long long L;


void init()
{
    memset(head,-1,sizeof(head));
    tot = 0;
    kongbai.clear();
}


void addedge(int u,int v,long long cost)
{
    edge[tot].u = u;
    edge[tot].to = v;
    edge[tot].next = head[u];
    edge[tot].cost = cost;
    head[u] = tot++;
}




long long spfa(int s,int t)
{
    memset(vis,false,sizeof(vis));
    memset(path,inf,sizeof(path));
    path[s] = 0;
    vis[s] = true;
    queue<int> sk;
    sk.push(s);
    while(!sk.empty())
    {
        int u = sk.front();
        sk.pop();
        vis[u] = false;
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int to = edge[i].to;
            if(path[to]>path[u] + edge[i].cost)
            {
                path[to] = path[u] + edge[i].cost;
                if(!vis[to])
                {
                    vis[to] = true;
                    sk.push(to);
                }
            }
        }
    }
    return path[t];
}


int main()
{
    init();
    cin>>n>>m>>L>>s>>t;
    int a,b;
    long long cost;
    for(int i=0; i<m; i++)
    {
        cin>>a>>b>>cost;
        if(!cost)
        {
            cost=1e9;
            kongbai.push_back(tot);


        }
        addedge(a,b,cost);
        addedge(b,a,cost);


    }
    //全都变为最大,求最短路


    long long dangiqnazuiduanlu=spfa(s,t);
    if(dangiqnazuiduanlu<L)//都极限大了,总量还是小了,那么没得救了
    {
        cout<<"NO"<<endl;
        return 0;
    }
    else if(dangiqnazuiduanlu==L)//如果相等
    {
       cout<<"YES"<<endl;
       for(int i=0; i<tot; i+=2)
          cout<<edge[i].u<<" "<<edge[i].to<<" "<<edge[i].cost<<endl;
        return 0;
    }
    else//否则
    {
        int numm=kongbai.size();
        for(int i=0; i<numm;i++)//枚举空白
        {
            int now = kongbai[i];//第几条路可以带换
            edge[now].cost = edge[now^1].cost = 1;
            dangiqnazuiduanlu=spfa(s,t);
            if(dangiqnazuiduanlu<=L)//小了,我们让当前更改的多加点即可
            {
                edge[now].cost = edge[now^1].cost = L - dangiqnazuiduanlu + 1;
                 cout<<"YES"<<endl;
                for(int i=0; i<tot; i+=2)
                cout<<edge[i].u<<" "<<edge[i].to<<" "<<edge[i].cost<<endl;
                return 0;
            }


        }
    }
    cout<<"NO"<<endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
void DFSTraverse(Graph graph) { for (int i = 1; i <= graph->vexnum; i++) visited[i] = false; for (int i = 1; i <= graph->vexnum; i++) { if (!visited[i]) DFS(graph, i); } } void DFS(Graph graph, int v) { visited[v] = true; cout << graph->list[v].data << " "; Node* header = graph->list[v].head; while (header) { if (!visited[header->vex]) { DFS(graph, header->vex); } header = header->next; } } void BFSTraverse(Graph graph) { queue<int> MyQueue; for (int i = 1; i <= graph->vexnum; i++) visited[i] = false; for (int i = 1; i <= graph->vexnum; i++) { if (!visited[i]) { visited[i] = true; cout << graph->list[i].data << " "; MyQueue.push(i); while (!MyQueue.empty()) { int front = MyQueue.front(); MyQueue.pop(); Node* header = graph->list[front].head; while (header) { if (!visited[header->vex]) { visited[header->vex] = true; cout << graph->list[header->vex].data << " "; MyQueue.push(header->vex); } header = header->next; } } } } } void printGraph(Graph graph) { int** arr = new int* [graph->vexnum + 1]; for (int i = 1; i <= graph->vexnum; i++) { arr[i] = new int[graph->vexnum + 1]; } for (int i = 1; i <= graph->vexnum; i++) { for (int j = 1; j <= graph->vexnum; j++) { arr[i][j] = 0; } } for (int i = 1; i <= graph->vexnum; i++) { Node* header = graph->list[i].head; while (header) { arr[i][header->vex] = header->weight; header = header->next; } } for (int i = 1; i <= graph->vexnum; i++) { for (int j = 1; j <= graph->vexnum; j++) { cout << arr[i][j] << " "; } cout << endl; } }代码讲解
最新发布
06-09

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值