怎么又做到三倍经验,五年计划都超额完成了
这几道题像极了.
想起来不难吧,要让边改变之后与原来的最短路差值最大,就把最短路上的边改了呗.
用一个队列来记录最短路上的边,然后枚举这个队列里的元素,依次改变,刷出最大值.
代码有点不好写,这次我加上注释了.
不要问我为什么变量名怎么这么长,最近沉迷代码补全.
P2176的代码:
#include<bits/stdc++.h>
using namespace std;
priority_queue< pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
queue<int>the_shortest_path;//保存下来最短路的路径
queue<int>before[110];//用来存每个点的前驱边
struct edge
{
int next,to,val,from;
}e[10010];//两倍开点
int n,m,size,mina=0x3f3f3f3f,minb=0x3f3f3f3f,ans=-0x3f3f3f3f;
int head[110],dis[110];
bool flag[110];
void edge_add(int,int,int);
void Dijstra(int);
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int a,b,v;
scanf("%d%d%d",&a,&b,&v);
edge_add(a,b,v);
edge_add(b,a,v);
}
Dijstra(1);
mina=dis[n];
the_shortest_path=before[n];
while(!the_shortest_path.empty())
{
for(int i=0;i<110;i++)while(before[i].size()!=0)before[i].pop();
int straw=the_shortest_path.front(),oppsite;
the_shortest_path.pop();
if(e[straw].to==e[straw+1].from)oppsite=straw+1;//因为是双向的边,就要这样把两倍都改了,这也是为什么之前的结构体里要写from
else oppsite=straw-1;
e[straw].val=e[straw].val+e[straw].val;
e[oppsite].val=e[oppsite].val+e[oppsite].val;
Dijstra(1);
minb=dis[n];
if(ans<minb-mina)ans=minb-mina;
e[straw].val/=2;
e[oppsite].val/=2;
}
printf("%d\n",ans);
return 0;
}
void edge_add(int from,int to,int val)
{
e[++size].to=to;
e[size].from=from;
e[size].val=val;
e[size].next=head[from];
head[from]=size;
}
void Dijstra(int start)
{
memset(dis,0x3f,sizeof(dis));
memset(flag,false,sizeof(flag));
dis[start]=0;
q.push(make_pair(dis[start],start));
while(!q.empty())
{
int node=q.top().second;
q.pop();
if(flag[node]==true)continue;
flag[node]=true;
for(int i=head[node];i!=-1;i=e[i].next)
{
int to=e[i].to;
int val=e[i].val;
if(dis[to]>dis[node]+val)
{
dis[to]=dis[node]+val;
before[to]=before[node];//继承node的前驱
before[to].push(i);//再加上这一次的边
q.push(make_pair(dis[to],to));
}
}
}
}
原文地址:https://www.cnblogs.com/Lemir3/p/11064220.html
时间: 2024-10-10 14:34:00