【CF 507E】Breaking Good

来源:互联网 发布:淘宝网女式运动服 编辑:程序博客网 时间:2024/06/10 04:05

【CF 507E】Breaking Good

双条件最短路
每个路有已搭建和未搭建两种状态 需要把经过的路都建起 为经过的路都拆掉
优先经过最少条路 同样少的路走改动(搭建+拆掉)最小的

最短路跑完后把最短的路上的路径标记一下
bfs输出拆除和搭建 在最短路径上的路 未建的搭建 不在的建好的拆掉

通过此题试了一下spfa的一个小优化还有dijkstra的优先队列优化
不过别看spfa加优化快了点 前两天做了个专门卡这个优化的题……想方设法让他多跑就是。。HDOJ 4889 有兴趣的可以去瞅瞅

此题代码如下:

//spfa 109ms#include <iostream>#include <cstdio>#include <cstring>#include <queue>#define sz 100000#define INF 0x3f3f3f3fusing namespace std;typedef struct Edge//邻接表建图{    int v,next,hs;    int in;}Edge;bool vis[sz+1];Edge eg[2*sz+2];int head[sz+1];int rep[sz+1],dis[sz+1],site[sz+1],pre[sz+1];//rep重建路数 dis经过路数 site当前点与前驱点间路下标 用以标记 pre前驱int alb,n,m,tp;void Add(int u,int v,int w){    eg[tp].v = v;    eg[tp].hs = w;    eg[tp].next = head[u];    eg[tp].in = 0;    head[u] = tp++;}void spfa(){    queue <int> q;    memset(vis,0,sizeof(vis));    memset(dis,INF,sizeof(dis));    memset(rep,INF,sizeof(rep));    int i,u,v,p,ned;    q.push(1);    dis[1]  = rep[1] = 0;    pre[1] = vis[1] = 1;    while(!q.empty())    {        u = q.front();        q.pop();        if(u == n) return;        for(i = head[u]; i != -1; i = eg[i].next)        {            ned = eg[i].hs^1;            v = eg[i].v;            if(dis[u]+1 < dis[v] || (dis[u]+1 == dis[v] && rep[u] + ned < rep[v]))            {                site[v] = i;                pre[v] = u;                dis[v] = dis[u]+1;                rep[v] = rep[u] + ned;                if(!vis[v])                {                    q.push(v);                    vis[v] = 1;                }            }        }    }}void Bfs(){    memset(vis,0,sizeof(vis));    queue <int> q;    q.push(1);    int i,u,v;    vis[1] = 1;    while(!q.empty())    {        u = q.front();        q.pop();        for(i = head[u]; i != -1; i = eg[i].next)        {            if(eg[i].in == -1) continue;            v = eg[i].v;            if(!eg[i].hs && eg[i].in)//路未建且在路径中            {                printf("%d %d 1\n",u,v);            }            else if(eg[i].hs && !eg[i].in)//路已建但不在路径中            {                printf("%d %d 0\n",u,v);            }            eg[i].in = eg[i^1].in = -1;            if(!vis[v])            {                q.push(v);                vis[v] = 1;            }        }    }    puts("");}int main(){    int u,v,w;    scanf("%d %d",&n,&m);    memset(head,-1,sizeof(head));    tp = alb = 0;    while(m--)    {        scanf("%d %d %d",&u,&v,&w);        Add(u,v,w);        Add(v,u,w);        if(w) alb++;//累加已建路数    }    spfa();    for(u = n; u != pre[u]; u = pre[u]) eg[site[u]].in = eg[site[u]^1].in = 1;//标记最短路径上的路    printf("%d\n",rep[n]*2 + alb - dis[n]);//rep+(alb-(dis-rep))    Bfs();    return 0;}
//spfa+优化93ms #include <iostream>#include <cstdio>#include <cstring>#include <queue>#define sz 100000#define INF 0x3f3f3f3fusing namespace std;typedef struct Edge{    int v,next,hs;    int in;}Edge;bool vis[sz+1];Edge eg[2*sz+2];int head[sz+1];int rep[sz+1],dis[sz+1],site[sz+1],pre[sz+1];int alb,n,m,tp;void Add(int u,int v,int w){    eg[tp].v = v;    eg[tp].hs = w;    eg[tp].next = head[u];    eg[tp].in = 0;    head[u] = tp++;}void spfa(){    deque <int> q;    memset(vis,0,sizeof(vis));    memset(dis,INF,sizeof(dis));    memset(rep,INF,sizeof(rep));    int i,u,v,p,ned;    q.push_front(1);    dis[1]  = rep[1] = 0;    pre[1] = vis[1] = 1;    while(!q.empty())    {        u = q.front();        q.pop_front();        if(u == n) return;        for(i = head[u]; i != -1; i = eg[i].next)        {            ned = eg[i].hs^1;            v = eg[i].v;            if(dis[u]+1 < dis[v] || (dis[u]+1 == dis[v] && rep[u] + ned < rep[v]))            {                site[v] = i;                pre[v] = u;                dis[v] = dis[u]+1;                rep[v] = rep[u] + ned;                if(!vis[v])                {                    if(!q.empty()) p = q.front();                    if(!q.empty() && (dis[v] < dis[p] || (dis[v] == dis[p] && rep[v] < rep[p])) )q.push_front(v);                    else q.push_back(v);                    vis[v] = 1;                }            }        }    }}void Bfs(){    memset(vis,0,sizeof(vis));    queue <int> q;    q.push(1);    int i,u,v;    vis[1] = 1;    while(!q.empty())    {        u = q.front();        q.pop();        for(i = head[u]; i != -1; i = eg[i].next)        {            if(eg[i].in == -1) continue;            v = eg[i].v;            if(!eg[i].hs && eg[i].in)            {                printf("%d %d 1\n",u,v);            }            else if(eg[i].hs && !eg[i].in)            {                printf("%d %d 0\n",u,v);            }            eg[i].in = eg[i^1].in = -1;            if(!vis[v])            {                q.push(v);                vis[v] = 1;            }        }    }    puts("");}int main(){    int u,v,w;    scanf("%d %d",&n,&m);    memset(head,-1,sizeof(head));    tp = alb = 0;    while(m--)    {        scanf("%d %d %d",&u,&v,&w);        Add(u,v,w);        Add(v,u,w);        if(w) alb++;    }    spfa();    for(u = n; u != pre[u]; u = pre[u]) eg[site[u]].in = eg[site[u]^1].in = 1;    printf("%d\n",rep[n]*2 + alb - dis[n]);    Bfs();    return 0;}
//dijkstra+优化108ms#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <vector>#define sz 100000#define INF 0x3f3f3f3fusing namespace std;typedef struct Edge{    int v,next,hs;    int in;}Edge;bool vis[sz+1];Edge eg[2*sz+2];int head[sz+1];int rep[sz+1],dis[sz+1],site[sz+1],pre[sz+1];int alb,n,m,tp;void Add(int u,int v,int w){    eg[tp].v = v;    eg[tp].hs = w;    eg[tp].next = head[u];    eg[tp].in = 0;    head[u] = tp++;}struct cmp{    bool operator() (int a,int b)    {        return dis[a] > dis[b] || (dis[a] == dis[b] && rep[a] > rep[b]);    }};void Dijkstra(){    priority_queue <int,vector<int>,cmp> q;    memset(vis,0,sizeof(vis));    memset(dis,INF,sizeof(dis));    memset(rep,INF,sizeof(rep));    dis[1]  = rep[1] = 0;    pre[1] = 1;    q.push(1);    int i,v,p,mm,j,ss,ned;    while(1)    {        p = q.top();        q.pop();        if(p == n) return;        vis[p] = 1;        for(j = head[p]; j != -1; j = eg[j].next)        {            v = eg[j].v;            ned = eg[j].hs^1;            if(!vis[v] && (dis[p] + 1 < dis[v] || (dis[p]+1 == dis[v] && rep[p] + ned < rep[v])))            {                dis[v] = dis[p] + 1;                rep[v] = rep[p] +ned;                site[v] = j;                pre[v] = p;                q.push(v);            }        }    }}void Bfs(){    memset(vis,0,sizeof(vis));    queue <int> q;    q.push(1);    int i,u,v;    vis[1] = 1;    while(!q.empty())    {        u = q.front();        q.pop();        for(i = head[u]; i != -1; i = eg[i].next)        {            if(eg[i].in == -1) continue;            v = eg[i].v;            if(!eg[i].hs && eg[i].in)            {                printf("%d %d 1\n",u,v);            }            else if(eg[i].hs && !eg[i].in)            {                printf("%d %d 0\n",u,v);            }            eg[i].in = eg[i^1].in = -1;            if(!vis[v])            {                q.push(v);                vis[v] = 1;            }        }    }    puts("");}int main(){    int u,v,w;    scanf("%d %d",&n,&m);    memset(head,-1,sizeof(head));    tp = alb = 0;    while(m--)    {        scanf("%d %d %d",&u,&v,&w);        Add(u,v,w);        Add(v,u,w);        if(w) alb++;    }    Dijkstra();    for(u = n; u != pre[u]; u = pre[u]) eg[site[u]].in = eg[site[u]^1].in = 1;    printf("%d\n",rep[n]*2 + alb - dis[n]);    Bfs();    return 0;}
0 0