POJ 1944
明天补上。。。
这道题的思路确实很精致。考虑到连的边肯定不会是一个环,所以至少有一个断点。于是,可以枚举这个断点。断点一确定,那么连边的走向也就确定了。用D【i】表示由i开始可以到达的最远点即可。对于中间被断开的点,保存[1,left],[right,n]即可。
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; const int N=1005; const int P=10005; int d[N]; struct ei{ int u,v; }edge[P]; int main(){ int n,p,u,v; while(scanf("%d%d",&n,&p)!=EOF){ for(int i=0;i<p;i++){ scanf("%d%d",&u,&v); edge[i].u=min(u,v); edge[i].v=max(u,v); } int mind=(1<<30); for(int i=1;i<=n;i++){ memset(d,-1,sizeof(d)); int ans=0,pos=-1; for(int e=0;e<p;e++){ if(edge[e].u<=i&&edge[e].v>i){ d[1]=max(d[1],edge[e].u); d[edge[e].v]=max(d[edge[e].v],n); ans=1; } else { d[edge[e].u]=max(d[edge[e].u],edge[e].v); } } for(int i=1;i<=n;i++){ if(pos==-1&&d[i]!=-1){ pos=i; } else{ if(d[i]!=-1){ if(i<=d[pos]&&d[i]>d[pos]) d[pos]=d[i]; else if(i>d[pos]){ ans+=d[pos]-pos; pos=i; } } } } ans+=d[pos]-pos; mind=min(ans,mind); } printf("%d\n",mind); } return 0; }