507E (Dijkstra+优先队列)

来源:互联网 发布:英语基础知识软件 编辑:程序博客网 时间:2024/04/28 04:50

// 给无向简单连通图的m条边,求从顶点1到顶点n的最短路,同时使得最短路径中标记为0的边数与不在最短路径中标记为1的边数之和最小,输出这些边。

//可以设边权为1,使用优先队列,当前路径长度小的优先,路径长度相等时,最短路径中标记为0的边少的优先。


 

#include<bits/stdc++.h>using namespace std;#define maxn 100005struct Edge{    int x,y,z;}edge[maxn<<1];struct Node{    int v,dis,num,pre;}node[maxn];struct cmp{    bool operator() (Node &x,Node &y)    {        return x.dis>y.dis||(x.dis==y.dis&&x.num>y.num);    }};vector<int>g[maxn];bool vis[maxn];bool used[maxn<<1];int n,m;priority_queue<Node,vector<Node>,cmp> Q;void solve(){    Node temp=Node{1,1,0,-1};    int i;    Q.push(temp);    memset(vis,0,sizeof(vis));    while(!Q.empty())    {        temp=Q.top();Q.pop();        if(vis[temp.v]) continue;        vis[temp.v]=1;        node[temp.v]=temp;        if(temp.v==n) break;        for(i=0;i<g[temp.v].size();++i)        {            int j=g[temp.v][i];            if(vis[edge[j].y]) continue;            if(edge[j].z) Q.push(Node{edge[j].y,temp.dis+1,temp.num,j});            else Q.push(Node{edge[j].y,temp.dis+1,temp.num+1,j});        }    }    int ans=0;    memset(used,0,sizeof(used));    i=temp.pre;    while(i!=-1)    {        used[i]=1;        i=node[edge[i].x].pre;    }    for(i=1;i<=m+m;i+=2)    {        if(used[i]||used[i+1])        {            if(edge[i].z==0)                 ++ans;        }        else if(edge[i].z==1)             ++ans;    }    printf("%d\n",ans);    for(i=1;i<=m+m;i+=2)    {        if(used[i]||used[i+1])        {            if(edge[i].z==0)  printf("%d %d 1\n",edge[i].x,edge[i].y);        }        else if(edge[i].z==1) printf("%d %d 0\n",edge[i].x,edge[i].y);    }}int main(){    int i;    cin>>n>>m;    for(i=1;i<=m+m;i+=2)    {        scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z);        edge[i+1].x=edge[i].y;        edge[i+1].y=edge[i].x;        edge[i+1].z=edge[i].z;        g[edge[i].x].push_back(i);        g[edge[i+1].x].push_back(i+1);    }    solve();    return 0;}



 

0 0