Description
给一张n个点m条边的无向图,对于一条点编号递增的链,设其链未点的度为degree,链长为len,那么这条链的美丽值为beauty=len*degree,问这张图上所有编号递增的链中的最大美丽值
Input
第一行为两个整数n和m表示点数和边数,之后m行每行两个整数u和v表示这张图上u点和v点间有边,保证无重边无自环(2<=n<=100000,1<=m<=200000)
Output
输出编号递增的链的最大美丽值
Sample Input
8 6
4 5
3 5
2 5
1 2
2 8
6 7
Sample Output
9
Solution
每个点的度数很好求,问题在于如何求以某个点结尾的编号递增的最长链的长度,设dp[v]为以点v为结尾的编号递增的链的长度最大值,那么我们有dp[v]=max(dp[v],dp[u]+1),其中u为所有和v相连的点中编号比v小的,那么这样就可以在O(m)的时间内得到所有点的dp值,从中找到dp[i]*degree[i]的最大值即为答案
Code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 222222
typedef long long ll;
struct node
{
int u,v;
}edge[maxn];
int n,m,degree[maxn],dp[maxn];
int cmp(node a,node b)
{
if(a.u==b.u)return a.v<b.v;
return a.u<b.u;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(degree,0,sizeof(degree));
memset(dp,0,sizeof(dp));
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
degree[u]++,degree[v]++;
if(u>v)swap(u,v);
edge[i].u=u,edge[i].v=v;
}
sort(edge,edge+m,cmp);
for(int i=0;i<m;i++)
dp[edge[i].v]=max(dp[edge[i].v],dp[edge[i].u]+1);
ll ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,1ll*(dp[i]+1)*degree[i]);
printf("%I64d\n",ans);
}
return 0;
}