CodeForces 507E Breaking Good(最短路)

来源:互联网 发布:淘宝wap访客是什么意思 编辑:程序博客网 时间:2024/05/20 03:07

题意:有n个点,m条边,你需要从1-n使得路径长度最短,并且走过的坏路要修,没走到的好路要炸,在最短路径的前提下使得需要的工程量最小。

思路:dp[i]表示到i点需要的工程量,dp[1]=所有的好路数目,中途经过一个好的要-1,经过一个坏的要+1,Dijkstra来确保是最短路径。

   其实这道题并不是很难, 就是在最短路上加上求一个影响值, 但是这道题我做了三天才做出来,我也是无语了, 想想我的错误有三, 路径打印, 控制输出, 标记数组的大小。 好在我都把弄明白了, 也不算亏了, 详细的解说都在代码中。
#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>#include<queue>using namespace std;const int maxn = 100000 + 10;//存边结构体struct Edge{    int from, to, z;};struct HeapNode{    int u, d;    bool operator < (const HeapNode& rhs) const    {        return d > rhs.d;    }};int d[maxn], p[maxn], F[maxn], vis[2 * maxn]; // vis数组为对边位置编号的标记数组,切记在无向图中vis的大小要为边数的二倍int n, m, sum;bool done[maxn];       //标记顶点是否计算过vector<int> G[maxn];  //存放边在edages中的位置vector<Edge> edges;   //存放边//初始化函数void inin()   {    memset(vis, 0, sizeof(vis));     memset(done, 0, sizeof(done));    memset(d, 99, sizeof(d));    memset(F, 0, sizeof(F));    for(int i = 0; i <= n; i++)        G[i].clear();    edges.clear();    sum = 0;}//存边的函数  注意无向图中要调用两次void AddEdge(int from, int to, int z) {    edges.push_back((Edge){from, to, z});    int k = edges.size();    G[from].push_back(k-1);    if(z)        sum++;}//求最短路void Dijkstra(int s){    priority_queue<HeapNode> q;    d[s] = 0;    F[s] = sum/2;    p[s] = -1;    //打印路径时,结束的标记,应与选数据中的第一条边区别开,第一条在图中存的位置编号为零,故不能为零,    q.push((HeapNode){s, 0});    while(!q.empty())    {        HeapNode x = q.top();        q.pop();        int u = x.u;        if(done[u])            continue;        done[u] = true;        for(int i = 0; i < G[u].size(); i++)        {            Edge e = edges[G[u][i]];            if(d[e.to] > d[u]+1)            {                d[e.to] = d[u] + 1;                if(e.z)                    F[e.to] = F[u] - 1;                else                    F[e.to] = F[u] + 1;                p[e.to] = G[u][i];                q.push((HeapNode){e.to, d[e.to]});            }            else if(d[e.to] == d[u]+1)            {                    int k ;                    if(e.z)                        k = F[u] - 1;                    else                        k = F[u] + 1;                    if(F[e.to] > k)                    {                        F[e.to] = k;                        p[e.to] = G[u][i];                    }            }        }    }}//求路径void bfs(int n){    if(n == -1)        return ;    vis[n] = 1;    bfs(p[edges[n].from]);}int main(){    int x, y, z;    while(~scanf("%d%d", &n, &m))    {        inin();        for(int i = 0; i < m; i++)        {            scanf("%d%d%d", &x, &y, &z);            AddEdge(x, y, z);            AddEdge(y, x, z);        }        Dijkstra(1);        bfs(p[n]);/*      循环求路径                int pre = n;        while(p[pre] != -1)        {            vis[p[pre]] = 1;            pre = edges[p[pre]].from;        }*/        printf("%d\n", F[n]);        for(int i = 0; i < 2*m; i+=2)            if((vis[i]||vis[i+1]) && !edges[i].z)                printf("%d %d 1\n", edges[i].from, edges[i].to);            else if(!vis[i] && !vis[i+1] && edges[i].z)                printf("%d %d 0\n", edges[i].from, edges[i].to);    }    return 0;}

0 0
原创粉丝点击