您的位置:首页 > 其它

poj 3249 Test for Job

2013-01-20 17:25 411 查看
【题意】

n个点m条有向边,每个点有一个权值v[i],求一条从入度为0的点到出度为0的点路径上的经过所有点权值之和最小值。保证:

t is guaranteed that each road appears exactly once, and there is no way to return to a previous city. (实际上是告诉无环)

1 ≤ n ≤ 100000, 0 ≤ m ≤
1000000

【题解】

第一开始拆点用spfa做结果一直T,后来就用记忆化搜索(dp)写了就A了。

拓扑排序+DP我写的会T……发现记忆化搜索是个好东西,既快又好写。看来我以后还是少写拓扑排序吧,反正都可转化为记忆化搜索。

【Code】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=210000;
const int inf=1<<30;
int v[maxn],dout[maxn];
int f[maxn];
vector<int>pre[maxn];
void dp(int x)
{
if(f[x]>-inf)return;
if(pre[x].size()==0)
{
f[x]=v[x];
return;
}

int tn=pre[x].size();
for(int i=0;i<tn;i++)
{
int y=pre[x][i];
dp(y);
if(f[y]+v[x]>f[x])f[x]=f[y]+v[x];
}
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{

for(int i=0;i<=n+1;i++)
{
pre[i].clear();
dout[i]=0;
v[i]=0;
}

for(int i=1;i<=n;i++)
scanf("%d",&v[i]);

for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
dout[x]++;
pre[y].push_back(x);
}

for(int i=0;i<=n+1;i++)
f[i]=-inf;

for(int i=1;i<=n;i++)
if(dout[i]==0)
{
pre[n+1].push_back(i);
}

dp(n+1);
printf("%d\n",f[n+1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: