1、POJ1258
水水的prim……不过poj上硬是没过,wikioi上的原题却过了

1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 using namespace std; 5 const int maxn=100,inf=1e8; 6 int d[maxn+50],g[maxn+50][maxn+50],ans=0,n; 7 bool v[maxn+50]; 8 int main() 9 { 10 scanf("%d",&n); 11 for(int i=1;i<=n;++i) 12 for(int j=1;j<=n;++j) 13 { 14 scanf("%d",&g[i][j]); 15 if(g[i][j]==0) g[i][j]=inf; 16 } 17 memset(v,0,sizeof(v)); 18 for(int i=1;i<=n;++i) d[i]=g[1][i]; 19 d[1]=0; 20 v[1]=1; 21 for(int j=2;j<=n;++j) 22 { 23 int m=inf,k=j; 24 for(int i=1;i<=n;++i) 25 if(v[i]==0&&d[i]<m) m=d[i],k=i; 26 ans+=m; 27 v[k]=1; 28 for(int i=1;i<=n;++i) 29 if(v[i]==0&&g[k][i]<d[i]) d[i]=g[k][i]; 30 } 31 printf("%d",ans); 32 return 0; 33 }
2、POJ1273
sap,不过就是在标号的时候有点小失误浪费了些时间,就是应该是d[1]=n+1时才推出,不然最后一次没有增广

1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 const int maxn=200,maxm=200,inf=1e8; 7 struct wjmzbmr 8 { 9 int to,flow; 10 }e[maxm*2+50]; 11 vector<int> g[maxn+50]; 12 int n,m,ans=0,d[maxn+50],dv[maxn+50]; 13 int dfs(int k,int flow) 14 { 15 if (k==n) return flow; 16 int s=0; 17 for(int i=0;i<g[k].size();++i) 18 { 19 wjmzbmr t=e[g[k][i]]; 20 if(t.flow<=0||d[k]!=d[t.to]+1) continue; 21 int x=dfs(t.to,min(flow-s,t.flow)); 22 e[g[k][i]].flow-=x; 23 e[g[k][i]^1].flow+=x; 24 s+=x; 25 if(s==flow) return s; 26 } 27 if(d[1]==n+1) return s; 28 --dv[d[k]]; 29 if(dv[d[k]]==0) d[1]=n+1; 30 d[k]++; 31 dv[d[k]]++; 32 return s; 33 } 34 int main() 35 { 36 while (scanf("%d %d",&m,&n)!=EOF) 37 { 38 memset(dv,0,sizeof(dv)); 39 for(int i=0;i<=n;++i) d[i]=1; 40 ans=0; 41 for(int i=0;i<=n;++i) g[i].clear(); 42 int l=0; 43 for(int i=1;i<=m;++i) 44 { 45 int a,b,c; 46 scanf("%d %d %d",&a,&b,&c); 47 e[l].to=b,e[l].flow=c,g[a].push_back(l); 48 ++l; 49 e[l].to=a,e[l].flow=0,g[b].push_back(l); 50 ++l; 51 } 52 dv[1]=n; 53 while(d[1]<=n) ans+=dfs(1,inf); 54 printf("%d ",ans); 55 } 56 return 0; 57 }
3、POJ1274
匈牙利算法,此题注意多组数据

1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 #include<vector> 5 using namespace std; 6 const int maxn=400; 7 int d[maxn+50]={0},n,m; 8 bool f[maxn+50]={0}; 9 vector<int> g[maxn+50]; 10 bool dfs(int k) 11 { 12 for(int i=0;i<g[k].size();++i) 13 if(!f[g[k][i]]) 14 { 15 f[g[k][i]]=1; 16 if(d[g[k][i]]==0||dfs(d[g[k][i]])) 17 { 18 d[g[k][i]]=k; 19 return true; 20 } 21 } 22 return false; 23 } 24 int main() 25 { 26 while(scanf("%d %d",&n,&m)!=EOF) 27 { 28 for(int i=0;i<=n+m;++i) g[i].clear(); 29 for(int i=1;i<=n;++i) 30 { 31 int x; 32 scanf("%d",&x); 33 for(int j=1;j<=x;++j) 34 { 35 int y; 36 scanf("%d",&y); 37 g[i].push_back(y+n); 38 g[y+n].push_back(i); 39 } 40 } 41 memset(d,0,sizeof(d)); 42 for(int i=1;i<=n;++i) 43 { 44 memset(f,0,sizeof(f)); 45 dfs(i); 46 } 47 int ans=0; 48 for(int i=n+1;i<=n+m;++i) 49 if(d[i]) ++ans; 50 printf("%d ",ans); 51 } 52 }
4、POJ2182
平衡树,用treap写的

1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<ctime> 5 const int maxn=8000; 6 int q[maxn+50],ans[maxn+50],n,p[maxn+50]={0}; 7 struct wjmzbmr 8 { 9 wjmzbmr* ch[2]; 10 int size,value,key; 11 int cmp(int x) 12 { 13 if(x==value) return -1; 14 return value<x; 15 } 16 void maintain() 17 { 18 size=1; 19 if(ch[0]!=NULL) size+=ch[0]->size; 20 if(ch[1]!=NULL) size+=ch[1]->size; 21 } 22 }; 23 wjmzbmr* root=NULL; 24 void rorate(wjmzbmr* &o,int d) 25 { 26 wjmzbmr *k=o->ch[d^1]; 27 o->ch[d^1]=k->ch[d]; 28 k->ch[d]=o; 29 o->maintain(); 30 k->maintain(); 31 o=k; 32 } 33 void insert(wjmzbmr* &o,int x) 34 { 35 if(o==NULL) 36 { 37 o=new wjmzbmr(); 38 o->ch[0]=o->ch[1]=NULL; 39 o->size=1; 40 o->value=x; 41 o->key=rand()%1000000000; 42 } 43 else 44 { 45 int d=o->cmp(x); 46 insert(o->ch[d],x); 47 if(o->ch[d]->key>o->key) rorate(o,d^1); 48 } 49 o->maintain(); 50 } 51 void remove(wjmzbmr* &o,int x) 52 { 53 int d=o->cmp(x); 54 if(d==-1) 55 if(o->ch[0]==NULL) o=o->ch[1]; 56 else 57 if(o->ch[1]==NULL) o=o->ch[0]; 58 else 59 { 60 int d1=(o->ch[0]->key>o->ch[1]->key); 61 rorate(o,d1); 62 remove(o->ch[d1],x); 63 } 64 else remove(o->ch[d],x); 65 if(o!=NULL) o->maintain(); 66 } 67 int kth(wjmzbmr* o,int k) 68 { 69 int l=0; 70 if(o->ch[0]!=NULL) l=o->ch[0]->size; 71 if(l+1==k) return o->value; 72 if(l+1<k) return kth(o->ch[1],k-l-1); 73 if(l+1>k) return kth(o->ch[0],k); 74 } 75 int main() 76 { 77 freopen("ce.in","r",stdin); 78 freopen("ce.out","w",stdout); 79 scanf("%d",&n); 80 for(int i=2;i<=n;++i) scanf("%d",&q[i]); 81 for(int i=1;i<=n;++i) insert(root,i); 82 for(int i=n;i>=2;--i) ans[i]=kth(root,q[i]+1),remove(root,ans[i]),p[ans[i]]=1; 83 for(int i=1;i<=n;++i) if(p[i]==0) ans[1]=i; 84 for(int i=1;i<=n;++i) printf("%d ",ans[i]); 85 return 0; 86 }
5、POJ2186
有向图强联通,我用2次dfs写的,觉得挺好写的且可以直接撸出拓扑序列,尽管慢一些

1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 const int maxn=1e5,inf=1e9; 7 vector < int > g[maxn+50],g1[maxn+50],g2[maxn+50]; 8 bool v[maxn+50]; 9 int n,m,color[maxn+50],t[maxn+50],len,c,d[maxn+50]; 10 void dfs(int k) 11 { 12 v[k]=1; 13 for(int i=0;i<g[k].size();++i) 14 if(!v[g[k][i]]) dfs(g[k][i]); 15 ++len; 16 t[len]=k; 17 } 18 void dfs1(int k) 19 { 20 v[k]=1; 21 color[k]=c; 22 for(int i=0;i<g1[k].size();++i) 23 if(!v[g1[k][i]]) dfs1(g1[k][i]); 24 } 25 bool check2(int a,int b) 26 { 27 if(a==b) return 0; 28 for(int i=0;i<g2[a].size();++i) 29 if(g2[a][i]==b) return 0; 30 return 1; 31 } 32 int main() 33 { 34 35 while(scanf("%d %d",&n,&m)!=EOF) 36 { 37 c=0; 38 len=0; 39 memset(d,0,sizeof(d)); 40 for(int i=0;i<=n;++i) g[i].clear(),g1[i].clear(),g2[i].clear(); 41 for(int i=1;i<=m;++i) 42 { 43 int x,y; 44 scanf("%d %d",&x,&y); 45 g[x].push_back(y); 46 g1[y].push_back(x); 47 } 48 memset(v,0,sizeof(v)); 49 memset(t,0,sizeof(t)); 50 for(int i=1;i<=n;++i) if(!v[i]) dfs(i); 51 memset(v,0,sizeof(v)); 52 for(int i=len;i>=1;--i) if(!v[t[i]]) ++c,dfs1(t[i]); 53 for(int i=1;i<=n;++i) 54 for(int j=0;j<g[i].size();++j) 55 if(check2(color[i],color[g[i][j]])) 56 g2[color[i]].push_back(color[g[i][j]]),++d[color[i]]; 57 int s=0,x=0; 58 for(int i=1;i<=c;++i) if(d[i]==0) ++s,x=i; 59 if(s>1) printf("0 "); 60 else 61 { 62 int ans=0; 63 for(int i=1;i<=n;++i) 64 if(color[i]==x) ++ans; 65 printf("%d ",ans); 66 } 67 } 68 return 0; 69 }
6、POJ2187
凸包,求最远对,Andrew算法:水平竖直排序+正反两边维护 O(nlogn)

1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 using namespace std; 5 const int maxn=50000; 6 struct wjmzbmr 7 { 8 int x,y; 9 bool operator < (const wjmzbmr& a) const 10 { 11 return (x<a.x)||(x==a.x&&y<a.y); 12 } 13 }a[maxn+50]; 14 int n,s[maxn+50],q[maxn+50],m=0,len=0; 15 int cross(int x1,int y1,int x2,int y2) 16 { 17 return (x1*y2-y1*x2); 18 } 19 int main() 20 { 21 scanf("%d",&n); 22 for(int i=1;i<=n;++i) scanf("%d %d",&a[i].x,&a[i].y); 23 sort(a+1,a+n+1); 24 m=2; 25 s[1]=1,s[2]=2; 26 for(int i=3;i<=n;++i) 27 { 28 while(m>=2&&cross(a[s[m]].x-a[s[m-1]].x,a[s[m]].y-a[s[m-1]].y,a[i].x-a[s[m]].x,a[i].y-a[s[m]].y)<=0) --m; 29 s[++m]=i; 30 } 31 s[++m]=n-1; 32 int k=m; 33 for(int i=n-2;i>=1;--i) 34 { 35 while(m>=k&&cross(a[s[m]].x-a[s[m-1]].x,a[s[m]].y-a[s[m-1]].y,a[i].x-a[s[m]].x,a[i].y-a[s[m]].y)<=0) --m; 36 s[++m]=i; 37 } 38 int ans=0; 39 for(int i=1;i<=m-1;++i) 40 for(int j=i+1;j<=m;++j) 41 if((a[s[i]].x-a[s[j]].x)*(a[s[i]].x-a[s[j]].x)+(a[s[i]].y-a[s[j]].y)*(a[s[i]].y-a[s[j]].y)>ans) ans=(a[s[i]].x-a[s[j]].x)*(a[s[i]].x-a[s[j]].x)+(a[s[i]].y-a[s[j]].y)*(a[s[i]].y-a[s[j]].y); 42 printf("%d",ans); 43 return 0; 44 }
7、POJ2019
二维RMQ,但是有点细节要注意:就是以后打1<<(..)的时候一定要将整个都打上括号,因为<<优先级是最高的……这点小细节卡了不少时间

1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 const int maxn=250; 7 int mx[maxn+5][maxn+5][10],mi[maxn+5][maxn+5][10],n,b,m; 8 int qmax(int lx,int ly,int rx,int ry) 9 { 10 int r=int(log(double(ry-ly+1))/log(double(2))),ans=-1; 11 for(int i=lx;i<=rx;++i) 12 ans=max(ans,max(mx[i][ly][r],mx[i][ry-(1<<r)+1][r])); 13 return ans; 14 } 15 int qmin(int lx,int ly,int rx,int ry) 16 { 17 int r=int(log(double(ry-ly+1))/log(double(2))),ans=1e8; 18 for(int i=lx;i<=rx;++i) 19 ans=min(ans,min(mi[i][ly][r],mi[i][ry-(1<<r)+1][r])); 20 return ans; 21 } 22 int main() 23 { 24 freopen("ce.in","r",stdin); 25 freopen("ce.out","w",stdout); 26 while(scanf("%d %d %d",&n,&b,&m)!=EOF) 27 { 28 for(int i=1;i<=n;++i) 29 for(int j=1;j<=n;++j) 30 { 31 scanf("%d",&mx[i][j][0]); 32 mi[i][j][0]=mx[i][j][0]; 33 } 34 int r=int(log(double(n))/log(double(2))); 35 for(int k=1;k<=n;++k) 36 for(int j=1;j<=r;++j) 37 for(int i=1;i+(1<<(j-1))-1<=n;++i) 38 { 39 mx[k][i][j]=max(mx[k][i][j-1],mx[k][i+(1<<(j-1))][j-1]); 40 mi[k][i][j]=min(mi[k][i][j-1],mi[k][i+(1<<(j-1))][j-1]); 41 } 42 for(int i=1;i<=m;++i) 43 { 44 int lx,ly,rx,ry; 45 scanf("%d %d",&lx,&ly); 46 rx=min(n,lx+b-1); 47 ry=min(ly+b-1,n); 48 printf("%d ",qmax(lx,ly,rx,ry)-qmin(lx,ly,rx,ry)); 49 } 50 } 51 return 0; 52 }
8、POJ1988
并查集,练练手

1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 using namespace std; 5 const int maxn=300000; 6 int f[maxn+50],n,before[maxn+50],len[maxn+50]; 7 int find(int x) 8 { 9 if(f[x]==x) return x; 10 int k=find(f[x]); 11 len[x]=len[k]; 12 before[x]+=before[f[x]]; 13 return f[x]=k; 14 } 15 int main() 16 { 17 scanf("%d ",&n); 18 for(int i=1;i<=n;++i) f[i]=i,len[i]=1,before[i]=0; 19 for(int i=1;i<=n;++i) 20 { 21 char c; 22 scanf("%c ",&c); 23 if(c=='M') 24 { 25 int x,y; 26 scanf("%d %d ",&x,&y); 27 x=find(x),y=find(y); 28 if(x!=y) 29 { 30 f[x]=y; 31 before[x]=len[y]; 32 len[y]+=len[x]; 33 } 34 } 35 else 36 { 37 int q; 38 scanf("%d ",&q); 39 int k=find(q); 40 printf("%d ",before[q]); 41 } 42 } 43 return 0; 44 }
9、POJ3666
静态主席树求区间k小(此题是求中位数,左偏树也能搞)

1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 using namespace std; 5 const int maxn=2000; 6 struct wjmzbmr 7 { 8 int l,r,ls,rs,sum; 9 }f[maxn*20]; 10 struct fotile96 11 { 12 int l,r,mid; 13 }stack[maxn+50]; 14 int a[maxn+50],sorta[maxn+50],root[maxn+50],n,len=0; 15 int build(int l,int r) 16 { 17 int k=++len; 18 f[k].l=l,f[k].r=r,f[k].ls=f[k].rs=f[k].sum=0; 19 if(l==r) return len; 20 int mid=(l+r)>>1; 21 f[k].ls=build(l,mid); 22 f[k].rs=build(mid+1,r); 23 return k; 24 } 25 int change(int root,int x) 26 { 27 int k=++len; 28 f[k]=f[root],f[k].sum+=1; 29 if(f[k].l==f[k].r) return k; 30 int mid=(f[k].l+f[k].r)>>1; 31 if(x<=mid) f[k].ls=change(f[k].ls,x);else f[k].rs=change(f[k].rs,x); 32 return k; 33 } 34 int ask(int a,int b,int k) 35 { 36 if(f[b].l==f[b].r) return f[b].r; 37 int mid=f[f[b].ls].sum-f[f[a].ls].sum; 38 if(k<=mid) return ask(f[a].ls,f[b].ls,k);else return ask(f[a].rs,f[b].rs,k-mid); 39 } 40 int main() 41 { 42 scanf("%d",&n); 43 for(int i=1;i<=n;++i) scanf("%d",&a[i]); 44 for(int i=1;i<=n;++i) sorta[i]=a[i]; 45 sort(sorta+1,sorta+n+1); 46 int q=1; 47 for(int i=2;i<=n;++i) if(sorta[i]!=sorta[q]) sorta[++q]=sorta[i]; 48 root[0]=build(1,q); 49 for(int i=1;i<=n;++i) 50 { 51 int x=lower_bound(sorta+1,sorta+q+1,a[i])-sorta; 52 root[i]=change(root[i-1],x); 53 } 54 len=1; 55 stack[len].l=stack[len].r=1,stack[len].mid=a[1]; 56 for(int i=2;i<=n;++i) 57 { 58 ++len; 59 stack[len].l=stack[len].r=i,stack[len].mid=a[i]; 60 while (len>1&&stack[len].mid<stack[len-1].mid) 61 { 62 stack[len-1].r=stack[len].r; 63 --len; 64 stack[len].mid=sorta[ask(root[stack[len].l-1],root[stack[len].r],(stack[len].r-stack[len].l+1)/2+1)]; 65 } 66 } 67 int ans=0; 68 for (int i=1;i<=len;++i) 69 for (int j=stack[i].l;j<=stack[i].r;++j) 70 ans+=abs(a[j]-stack[i].mid); 71 printf("%d",ans); 72 return 0; 73 }