题目链接: http://gdutcode.sinaapp.com/problem.php?cid=1054&pid=4
题意: 给出一个图,有重边和自环,不能从编号大的往编号小的走,求从点1到点n的不超过K的最长路
分析:因为边的数量比较少,所以我们可以直接BFS来计算,对于有自环的路径,我们标记,然后在到达终点再统计,然后取最长路径。不过正解是动态规划,我们用 DP[i][j] 表示是否能够以长度j的路径到达点i,状态转移方程为:
for(int u=1;u<=n;u++)
{
for(int i=head0[u];i!=-1;i=edge0[i].next)
{
int w = edge0[i].w;
for(int j=w;j<=k;j++)
{
dp[u][j] |= dp[u][j-w];
}
}
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v = edge[i].v, w = edge[i].w;
for(int j=w;j<=k;j++)
{
dp[v][j] |= dp[u][j-w];
}
}
}
- AC代码:
/*************************************************************************
> File Name: test.cpp
> Author: Akira
> Mail: qaq.febr2.qaq@gmail.com
************************************************************************/
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <bitset>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <set>
#include <list>
#include <ctime>
#include <climits>
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))
using namespace std;
#define MaxN 2001
#define MaxM 3001
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
const int mod = 1E9+7;
const double eps = 1e-6;
#define bug cout<<88888888<<endl;
#define debug(x) cout << #x" = " << x;
int T,n,m,k;
struct Edge
{
int u,v,w,next;
}edge[MaxM],edge0[MaxM];
int cont,head[MaxN], cont0,head0[MaxN];
void add(int u, int v, int w)
{
edge[cont].u = u, edge[cont].v = v, edge[cont].w = w, edge[cont].next = head[u], head[u] = cont++;
}
void add0(int u, int v, int w)
{
edge0[cont0].u = u, edge0[cont0].v = v, edge0[cont0].w = w, edge0[cont0].next = head0[u], head0[u] = cont0++;
}
int dp[MaxN][MaxM];
void solve()
{
dp[1][0] = 1;
for(int u=1;u<=n;u++)
{
for(int i=head0[u];i!=-1;i=edge0[i].next)
{
int w = edge0[i].w;
for(int j=w;j<=k;j++)
{
dp[u][j] |= dp[u][j-w];
}
}
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v = edge[i].v, w = edge[i].w;
for(int j=w;j<=k;j++)
{
dp[v][j] |= dp[u][j-w];
}
}
}
int ans = -1;
for(int j=0;j<=k;j++)
{
if(dp[n][j]) ans = j;
}
printf("%d\n", ans);
}
void init()
{
cont = cont0 = 0;
MST(head,-1);
MST(head0,-1);
CLR(dp);
}
int main()
{
scanf("%d", &T);
while(T--)
{
init();
scanf("%d%d%d", &n, &m, &k);
int a,b,c;
while(m--)
{
scanf("%d%d%d", &a, &b, &c);
if(a==b) add0(a,b,c);
else
{
if(a>b) add(b,a,c);
else add(a,b,c);
}
}
solve();
}
}