要求: 求最长的尾巴数 和 身上的刺的数的乘积最大;
解决办法: 首先求出每个顶点的最大刺数 这个应该蛮好求的, 直接将每个点比它大的入度求出来就可以了;
然后球每个顶点的最长尾巴数, 思路是排序加二分求; 先求出到第一个数的最长的序列, 然后依次求第二个数, 第三个数;方法是排序加二分;
我的代码:
#include<bits/stdc++.h>
#define memset(x) memset(x, 0, sizeof(x))
using namespace std;
const int maxn = 1e5 + 100;
struct node {
int x, y;
int input(int xx, int yy) {
x = xx;
y = yy;
}
bool friend operator < (node aa, node bb) {
if(aa.x == bb.x)
return aa.y < bb.y;
return aa.x < bb.x;
}
} a[maxn * 6];
struct no {
int first, endd, midd;
} d[maxn * 3];
int b[maxn * 3];
int c[maxn * 3];
int main() {
//freopen("out.txt", "r", stdin);
int n,m;
memset(a);
memset(b);
memset(c);
scanf("%d %d", &n, &m);
for(int i = 1; i <= 2 * m; i += 2) {
int xx, yy;
scanf("%d %d", &xx, &yy);
b[xx]++;
b[yy]++;
a[i].input(xx, yy);
a[i+1].input(yy, xx);
}
sort(a, a + 2 * m + 1);
for(int i = 1; i <= 2 * m; i++) {
d[a[i].x].midd++;
}
for(int i = 1; i <= n; i++) {
d[i].first = d[i - 1].endd;
d[i].endd = d[i - 1].endd + d[i].midd;
}
// for(int i = 1; i <= n; i++) {
// cout<< i <<" "<<d[i].first << " " << d[i].endd<< " " << d[i].midd << endl;
// }
// cout<<endl<<endl<<endl;
for(int i = 1; i <= n; i++)
c[i] = 1;
for(int i = 1; i <= n; i++) {
int maxx = 0;
for(int j = d[i].first + 1; j <= d[i].endd; j++) {
int start = d[j].first + 1;
if(i == a[j].x && i > a[j].y)
maxx= max(maxx, c[a[j].y]);
//cout <<" i = "<< i <<" j = "<< j <<" a[j].y = " << a[j].y<<" maxx " <<maxx<<endl;
}
c[i] = maxx + 1;
}
long long ans = 0;
// for(int i = 1; i <= n; i++)
// cout<< i <<" " << b[i] << " " <<c[i]<<endl;
for(int i = 1; i <= n; i++)
{
long long tem = (long long) b[i] * c[i];
ans = max(ans, tem);
}
cout<<ans;
}