您的位置:首页 > 其它

hdu 5385 The path

2015-08-15 09:33 309 查看
HDU 5385
构造题

使用贪心法构造,因为保证有解,点2或n至少有一个直接与点1相连

上述结论可以用反证法证明。

假若2和n不直接与1相连,那么必存在点x直接与1相连,间接与2,n相连。这种情况下无论如何设置边权,都有d[x]<d[2]&&d[x]<d
,与已知矛盾

那么可以按照每次添加两头的点与1相连,记添加时间为1到该点的最短路,边添加边计算边权

然后不在最短路树上的边权都设为n即可,这样不会使最短路树发生变化

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=100008;
struct edge{
int v,i;
};
int w[maxn];
vector<edge>    g[maxn];
int uni[maxn],dis[maxn];
void solve(int n)
{
int v,idx,i;
int left=2,right=n;
dis[1]=0;int ti=0;
while(left<right)
{
for(i=0;i<g[left].size();i++)
{
v=g[left][i].v;
idx=g[left][i].i;
if(uni[v]==1)
{
dis[left]=ti+1;
w[idx]=dis[left]-dis[v];
uni[left++]=1;
ti++;
break;
}
}
if(left>=right)    break;
for(i=0;i<g[right].size();i++)
{
v=g[right][i].v;
idx=g[right][i].i;
if(uni[v]==1)
{
dis[right]=ti+1;
w[idx]=dis[right]-dis[v];
uni[right--]=1;
ti++;
break;
}
}
}
}
int main()
{
int i,j,t,n,m,u,v;
edge pp;
//freopen("1006.in","r",stdin);
//    freopen("1011.txt","w",stdout);
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
g[i].clear();
for(i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
pp.i=i;
pp.v=u;
g[v].push_back(pp);
}
for(i=1;i<=n;i++)
uni[i]=i;
memset(w,-1,sizeof(w));
solve(n);
for(i=1;i<=m;i++)
{
if(w[i]==-1)
printf("%d\n",n);
else
printf("%d\n",w[i]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: