Codeforces Round #261 (Div. 2) E. Pashmak and Graph DP

时间:2023-02-01 22:18:06

http://codeforces.com/contest/459/problem/E

不明白的是我的代码为啥AC不了,我的是记录we[i]以i为结尾的点的最大权值得边,然后wa在第35  36组数据

然后参考答案了,然后----网上一份题解


大意: 给出一个带权有向图,求经过的边权绝对上升的最长路径(可能是非简单路径,即可能经过一个点多次)所包含的边数。

题解: 对边按权值排序后,从小到大搞。

设q[x]为已经搞过的边组成的以x点为终点的最长路径包含的边数。

设当前边e[i]为从u到v的边,由于我们是按权值排序好的,只要没有相同的权值,我们就可以q[v]=max(q[v], q[u]+1)。

但是是有相同的权值的,我们直接这样搞,相同权值的可能会连出一条路,是不符合要求的,像第一个样例会输出3,怒萎。

所以相同权值的要特殊搞。我希望相同权值的不是一个个更新,而是一起更新,所以我把相同权值的先不更新,而是压入vector中,统计完这个权值的所有边,再将其一起从vector中取出更新。发现,有些相同权值的边连到的是同一个点,我希望用更长的路来更新这个点,所以对vector排序,后更新更长的。

AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;

#define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout)
const ll ll_INF = ((ull)(-1))>>1;
const double EPS = 1e-8;
const int INF = 100000000;
const int MAXN = 4*(1e6)+100;
struct Edge
{
    int from,to,w;
}e[MAXN];
int n,m;
int dp[MAXN],we[MAXN];

inline void add(int u,int v,int w,int k)
{
    e[k].from=u;
    e[k].to=v;
    e[k].w=w;
}

void init()
{
    CL(dp,0);
    CL(we,0);
    //same.clear();
}

bool cmp(const Edge a, const Edge b)
{
     return a.w<b.w;
}

int main()
{
    //IN("E.txt");
    int u,v,w;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w,i);
        }
        sort(e,e+m,cmp);
        int mmax=0;
        for(int i=0,pos=0;i<m;i++)
        {
            dp[i]=we[e[i].from]+1;
            if(e[i].w!=e[i+1].w)
            {
                for(int j=pos;j<=i;j++)
                {
                    we[e[j].to]=max(we[e[j].to],dp[j]);
                }
                pos=i+1;
            }
            mmax=max(mmax,dp[i]);
        }

        printf("%d\n",mmax);
    }
    return 0;
}

WA而不知道原因的代码,就是记录最大权值的结尾

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;

#define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout)
const ll ll_INF = ((ull)(-1))>>1;
const double EPS = 1e-8;
const int INF = 100000000;
const int MAXN = 4*(1e6)+100;
struct Edge
{
    int from,to,w;
}e[MAXN];
int n,m;
int dp[MAXN],we[MAXN];

inline void add(int u,int v,int w,int k)
{
    e[k].from=u;
    e[k].to=v;
    e[k].w=w;
}

void init()
{
    CL(dp,0);
    CL(we,0);
}

bool cmp(const Edge a, const Edge b)
{
    if(a.w!=b.w)
        return a.w<b.w;
    else
    {
        if(a.from!=b.from)
            return a.from<b.from;
        else
            return a.to<b.to;
    }
}


int main()
{
    //IN("E.txt");
    int u,v,w;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w,i);
        }
        sort(e,e+m,cmp);
        int mmax=0;
        for(int i=0;i<m;i++)
        {
            u=e[i].from;
            v=e[i].to;
            if(e[i].w > we[u])
            {
                if(dp[u]+1>dp[v])
                {
                    we[v]=e[i].w;
                    dp[v]=dp[u]+1;
                }
                if(dp[u]+1 == dp[v])
                    we[v]=min(we[v],e[i].w);
            }
            //if(e[i].w == we[u])
            mmax=max(mmax,dp[v]);
            mmax=max(mmax,dp[u]);
        }
        printf("%d\n",mmax);
    }
    return 0;
}