T1
给定有向图,问每个点可以到达的点的编号最大值
如果从b可以沿反向边走到a,那么从a也可以沿正向边走到b
为了避免重复更新每个点的答案,应该按编号从大到小的顺序枚举终点,如果当前枚举的点没有被访问过,那么就把当前点当作终点,沿反向边dfs更新其他没有被访问过的点的答案
因为如果这个点曾经被访问过,那么这个点可以到达的点的编号最大值一定大于当前枚举的终点编号,所以每次只需要更新没被访问过的点即可
1 #include <cstdio> 2 struct E{ 3 int next,to; 4 }e[100001]; 5 int n,m,u,v,root,sz=0,head[100001],a[100001]; 6 void insert(int u,int v) 7 { 8 sz++; 9 e[sz].next=head[u]; 10 head[u]=sz; 11 e[sz].to=v; 12 } 13 void dfs(int x) 14 { 15 a[x]=root; 16 for (int i=head[x];i;i=e[i].next) 17 if (a[e[i].to]==0) 18 { 19 //printf("%d->%d\n",x,e[i].to); 20 dfs(e[i].to); 21 } 22 } 23 int main() 24 { 25 scanf("%d%d",&n,&m); 26 for (int i=1;i<=m;i++) 27 { 28 scanf("%d%d",&u,&v); 29 insert(v,u); 30 } 31 for (int i=n;i>=1;i--) 32 if (a[i]==0) 33 { 34 root=i; 35 dfs(i); 36 } 37 for (int i=1;i<=n;i++) printf("%d ",a[i]); 38 }
T2
http://blog.csdn.net/greatwjj/article/details/14518345
自己做的太垃圾了……我一开始推出a[i]-i <=a[j]-j的时候,还以为这道题要用斜率优化,其实形式和原来的一样,还是LIS,但是需要优化成$O(nlogn)$……
由于要修改最少的数字使数列单调递增,所以要最大化利用数列中已有的上升子序列,其实这道题就是LIS,但是由于只能改成整数,所以还有个限制条件p[i].a-p[j].a>=p[i].n-p[j].n
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 using namespace std; 5 struct P{ 6 int n,a; 7 }p[100001]; 8 int n,ans=0,f[100001]; 9 bool cmp(P a,P b) 10 { 11 return a.a<b.a; 12 } 13 int main() 14 { 15 scanf("%d",&n); 16 for (int i=1;i<=n;i++) 17 { 18 f[i]=1; 19 p[i].n=i; 20 scanf("%d",&p[i].a); 21 } 22 sort(p+1,p+n+1,cmp); 23 for (int i=1;i<=n;i++) 24 for (int j=1;j<i;j++) 25 if (p[i].n>p[j].n&&p[i].a-p[j].a>=p[i].n-p[j].n) 26 { 27 //printf("%d->%d\n",p[j].n,p[i].n); 28 f[i]=max(f[i],f[j]+1); 29 } 30 for (int i=1;i<=n;i++) ans=max(ans,f[i]); 31 printf("%d",n-ans); 32 }
T3
?又是数学
时间: 2024-12-29 11:19:20