Codeforces Gym 100342H Hard Test 构造

来源:互联网 发布:java中string转map 编辑:程序博客网 时间:2024/05/18 03:21

题目大意:

你需要造一个n个点m条边的有向图,使得所有点都能被1访问到,且dijkstra算法在该图上更新次数最多。为避免麻烦,你的构造方案应当使得每次更新后没有vis的有最小的dis的点只有一个(dis和vis都是dijkstra算法中的意义)。

胡扯:

这道题构造方法有很多种,我是用的最无脑的那一种

做法:

  • 注意到,要使得dijkstra更新次数最多,那么就是使得每一条边被枚举到的时候都进行一次有效更新。
  • 那么我们模拟dijkstra的过程
  • 先给每个点附上一个初始的dis
  • 边跑diskstra边建图
  • 每次建一条使得枚举到的点的dis变小的边即可
  • 如果不能建出正权边那就放弃,不建这条边

代码:

4558763 WHU_FFT H Accepted 19868 156 GNU G++ 4.9.2 793
#include <bits/stdc++.h>using namespace std;const int maxn = 2000 + 5,INF=1e7;int d[maxn],g[maxn][maxn];bool hg[maxn][maxn],v[maxn];int n,m;void solve(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)d[i]=i;    d[1]=0;    memset(v,0,sizeof v);    for(int i=1;i<=n;i++)    {        int mark=-1,mindis=INF;        for(int j=1;j<=n;++j)            if(!v[j] && d[j] < mindis)            {                mindis=d[j];                mark=j;            }        v[mark]=1;        for(int j=2;j<=n;++j){            if(mark==j || d[j]<=d[mark])continue;            m--;            d[j]--;             hg[mark][j]=true;            g[mark][j]=d[j]-d[mark];            //每次建一条使得使得d[j]-1的边             if(m==0)break;        }        if(m==0)break;    }    for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++)            if(hg[i][j])printf("%d %d %d\n",i,j,g[i][j]);}//模拟dijkstra int main(){    freopen("test.in","r",stdin);    freopen("test.out","w",stdout);    solve();    return 0;}
0 0
原创粉丝点击