Root :: AOAPC I: Beginning Algorithm Contests (Rujia Liu) Volume 7. Graph Algorithms and Implementation Techniques

    uva 10803 计算从任何一个点到图中的另一个点经历的途中必须每隔10千米 都必须有一个点然后就这样 floy 及解决了  

    ****************************************************************************************************************************

  

#include <iostream>
#include<cstdio>
#include<string.h>
#include<cmath>
using namespace std;
const double maxv=1.79769e+308;
struct point{
 double x,y;
}T[105];
double e[102][102];
int dcmp(double a){
   if(fabs(a)<0.00000001) return 0;
   if(a>0) return 1;
   else return -1;
}
double dist(int a,int b){
   return sqrt((T[a].x-T[b].x)*(T[a].x-T[b].x)+(T[a].y-T[b].y)*(T[a].y-T[b].y));
}
int main()
{
    int n,H=0,Tt;
    bool inq[105];
     scanf("%d",&Tt);
    while(Tt--){
            scanf("%d",&n);
         printf("Case #%d:\n",++H);
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&T[i].x,&T[i].y);
            for(int j=0;j<=i;j++){
                double t=dist(i,j);
                if(dcmp(10-t)<0) e[i][j]=e[j][i]=maxv;
                 else e[i][j]=e[j][i]=t;
            }
        }
        for(int k=0;k<n;k++)
            for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
            if(e[i][k]<maxv&&e[k][j]<maxv&&e[i][j]>e[i][k]+e[k][j]){
                e[i][j]=e[i][k]+e[k][j];
            }
            double ma=0;
        for(int i=0;i<n;i++)
            for(int j=i;j<n;j++)
            if(dcmp(e[i][j]>ma)>0) ma=e[i][j];
        if(dcmp(ma-maxv)==0) printf("Send Kurdy\n");
        else printf("%.4lf\n",ma);
         // if(Tt!=0)
          printf("\n");
    }
    return 0;
}

 

uva 567 题目说的是给了你 很多条边 然后让你计算出 有 n次的询问 要求你计算出 n次询问的最短的 路径是什么 。 直接一次Floyd


 

#include <cstdio>
#include <string.h>
#include<iostream>
using namespace std;
const int maxn=25;
int e[maxn][maxn];
int main()
{
 int n,i,j,k,numm=0;
while(scanf("%d",&n)==1)
{ 
for(i=1;i<=20;i++)
 for(j=1;j<=20;j++)
 e[i][j]=i!=j?30:0; 
for(i=0;i<n;i++){
 int a;scanf("%d",&a); 
e[1][a]=e[a][1]=1;
} for(i=2;i<=19;i++)
{ 
int num;scanf("%d",&num);
for(j=0;j<num;j++){ 
int a;
 scanf("%d",&a); 
e[i][a]=e[a][i]=1;
} 
} 
for(k=1;k<=20;k++)
 for(j=1;j<=20;j++)
 for(i=1;i<=20;i++)
 if(e[j][k]<30&&e[k][i])
 e[j][i]=e[j][i] < e[j][k]+e[k][i] ? e[j][i] : e[j][k]+e[k][i]; 
scanf("%d",&n); 
printf("Test Set #%d\n",++numm); 
for(i=0;i<n;i++)
 { 
int a,b;
scanf("%d%d",&a,&b);
printf("%2d to %2d:%2d\n",a,b,e[a][b]); 
} 
printf("\n"); 
} 
return 0;
}


 

uva 10034prim 最小生成树 由于是稠密图 就直接用了 prim 给了n个点的坐标 然后将他们 用最少的  墨水链接起来


 

#include <cstdio>
#include <string.h>
#include <iostream>
#include <cmath>
#include <queue>
using namespace std;
const int maxn=105;
const double INF=2147483647;

struct tree{
   int num;
   double G;
   bool operator <(const tree &A)const{
      return G>A.G;
   }
};
struct point{
  double x,y;
}node[maxn];
double e[maxn][maxn],d[maxn];
int n;
bool mark[maxn];
double dist(int a,int b){
  return sqrt((node[a].x-node[b].x)*(node[a].x-node[b].x)+(node[a].y-node[b].y)*(node[a].y-node[b].y));
}
int main()
{

	int t,f=0;
	cin>>t;
	while(t--){
	   if(f) printf("\n"); f=1;
	   scanf("%d",&n);
	    int i,j;
		double ans=0;
	   for(i=0;i<n;i++)
	   {
	     scanf("%lf%lf",&node[i].x,&node[i].y);
		 for(j=0;j<=i;j++)
			 e[i][j]=e[j][i]=dist(j,i);
	   }
	   for(i=0;i<n;i++)d[i]=INF;
       priority_queue<tree>Q;
	   memset(mark,false,sizeof(mark));
	   d[0]=0;
	   tree temp;
	   temp.G=0;temp.num=0;
	   Q.push(temp);
	   while(!Q.empty()){
	      temp=Q.top();Q.pop();
	      int x=temp.num;
		  if(mark[x]) continue;
		  ans+=temp.G;
		  mark[x]=true;
		   for(i=0;i<n;i++)
			   if(!mark[i]&&d[i]>e[x][i]){
			     tree T; 
				 d[i]=e[x][i];
				 T.num=i; T.G=d[i];
				 Q.push(T);
			   }
	   
	   }
	   printf("%.2lf\n",ans);
	
	}
	return 0;
}


 


 

#include <cstdio>
#include <string.h>
#include <iostream>
using namespace std;
const int maxn=105;
const int maxv=2147483647;
int map[maxn][maxn];
int c,s,q;
int main()
{
	 int i,j,k,num=0,f=0;
	while(scanf("%d%d%d",&c,&s,&q)==3){
		
		if(c+s+q==0) break;
	    if(f)printf("\n");f=1;
		for( i=1;i<=c;i++)
			for( j=1;j<=c;j++) map[i][j]=(i==j)?0:maxv;
		 for(i=0;i<s;i++){
		    int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			map[b][a]=map[a][b]=c;
		 }
		 for(k=1;k<=c;k++)
			 for(i=1;i<=c;i++)
				 for(j=1;j<=c;j++)
					 if(map[i][k]!=maxv&&map[k][j]!=maxv){
						 int a=map[i][k]>map[k][j]?map[i][k]:map[k][j];
						 if(map[i][j]>a) map[i][j]=a;
					 }
		  printf("Case #%d\n",++num);
		  for(i=0;i<q;i++){
		      int c1,c2;
			  scanf("%d%d",&c1,&c2);
			  if(map[c1][c2]==maxv) printf("no path\n");
			  else printf("%d\n",map[c1][c2]);
		  }
	}
}


 


#include<cstdio>
#include<string.h>
#include<iostream>
#include <cmath>
#include<queue>
using namespace std;
const int maxn=755;
const double maxv=1.796e+308; 
struct point{
 double x,y;
 point(double a=0,double b=0){ x=a;y=b; }
}T[maxn];
struct node{
   int num;
   double v;
   node(int a=0,double b=0){ num=a; v=b; }
   bool operator<(const node&A )const{
     return v>A.v;
   }
};
double e[maxn][maxn],d[maxn];
bool inq[maxn];
double dist(int a,int b){
  return sqrt((T[a].x-T[b].x)*(T[a].x-T[b].x)+(T[a].y-T[b].y)*(T[a].y-T[b].y));
}
int main()
{
	  int n,i,j,m;
	  while(scanf("%d",&n)==1){
		  for(i=1;i<=n;i++){
		    double x,y;
			scanf("%lf%lf",&T[i].x,&T[i].y);
            for(j=1;j<=i;j++)
				e[i][j]=e[j][i]=dist(j,i);
		  }
        scanf("%d",&m);
		for(i=0;i<m;i++){
		  int a,b;
		   scanf("%d%d",&a,&b);
		   e[a][b]=e[b][a]=0;
		}
        for(i=1;i<=n;i++)d[i]=maxv;
		memset(inq,false,sizeof(inq));
        d[1]=0;
		priority_queue<node> Q;
		Q.push(node(1,d[1]));
		node temp;
		double ans=0;
		while(!Q.empty()){
		    temp=Q.top();
			Q.pop();
			int x=temp.num;
			if(inq[x]) continue;
			inq[x]=true;
			ans+=d[x];
			for(i=1;i<=n;i++) if(!inq[i]&&e[x][i]!=maxv&&d[i]>e[x][i]){
			   d[i]=e[x][i];
               Q.push(node(i,d[i]));
			}
		}
        printf("%.2lf\n",ans);
	  }
	return 0;
}
 这题不怎么明白题意   我以为他说的  就样例 2 是那个  可以给三个城市用  没想到时 2个装备
    转载 在两个城市上  
  说说解题 这题说的 给了 很多的点  其中有S个点之间的 通信是不要花费的
   让后   然你 用最少的  花费 使他们之间有一条连线kruskal

 

#include<cstdio>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
 const int maxn=505;
struct edg{
  int a,b;
  double w;
  bool operator <(const edg &A)const {
	  return w<A.w; 
  }
}e[maxn*maxn];
int F[maxn],num,S,P;
double X[maxn],Y[maxn];
int per(int a){ 
	if(F[a]==a) return a;
	return F[a]=per(F[a]); 
}
double dist(int a,int b){ return sqrt((X[a]-X[b])*(X[a]-X[b])+(Y[a]-Y[b])*(Y[a]-Y[b]));}
void add(int a,int b,double F){ e[num].a=a; e[num].b=b; e[num].w=F; 
num++; }
int main()
{   
     int t,i,j; cin>>t;
	 while(t--){
		  num=0;
	      scanf("%d%d",&S,&P);
		  for(i=0;i<P;i++){
		      scanf("%lf%lf",&X[i],&Y[i]);
			  for(j=0;j<i;j++){
				  double d=dist(i,j);
                  add(i,j,d);add(j,i,d);
			  }
		  }
        for(i=0;i<P;i++)
			F[i]=i;
        sort(e,e+num);
        double ans=0; int GH=0;
        for(i=0;i<num;i++){
		   int x=per(e[i].a);
		   int y=per(e[i].b );
		   if(P-S<=GH){ break;  }
		   if(x!=y){   
			   F[x]=y; GH++;
			   if(P-S<=GH) { ans=e[i].w;break;}
		   }
		}
       printf("%.2lf\n",ans);
	 
	 }
	return 0;
}


 

 这题说的是给了一个有n个bug的软件 然后 用 m个补丁 去修补这 n个bug 
然后  这m个bug 用是有前提 的 然后 这样就非常 + - 0 分 别 是出现这种bug 没有这种bug 和出不出现都无所谓
然后  对于每一个补丁可以进行 用 f[0] f[1] 分别是 前提 0-- -++  f[0]=000;f[1]=011;b[0]=011;b[1]=100; 
当判断 是否可以同这个补丁的 时候 先与 f[0]与 然后与完后 如果和f[0]相等 且取反与f[1]与看是否与 f[1]相等

两个时是成立的时候就 可以了, 也用同样的方法去解变成的 值 然后来一次 bfs 就成功了 。



 

#include<cstdio>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
const int maxv=2147483647;
struct node{
   int t;
   int f[2],b[2];
}g[105];
struct bug{
  int num, t;
  bool operator<(const bug &A)const{
    return t>A.t;
  }
};
int d[1<<20];
bool mark[1<<20];
int n,m,maxt;
bool judget(int a,int x){
    int k,h=x;
	 k=h&g[a].f[0]; if(k!=g[a].f[0]) return false;
	h=~h;
	k=h&g[a].f[1];
	if(k!=g[a].f[1]) return false;
	return true;
}
int bian(int a,int x){
  int k,h=x,r;
  k=h|g[a].b[0];
  r=h&g[a].b[1];
  k=k-r;
  return k;
}
bool bfs(){
    priority_queue<bug>Q;
    bug t,y;
	bool f=0;
	t.num=(1<<n)-1;t.t=0; Q.push(t);
	while(!Q.empty()){
	   t=Q.top();Q.pop();
	   if(mark[t.num]) continue;
	   mark[t.num]=true;
	   if(t.num==0){ f=1; break;  }
	   for(int i=0;i<m;i++)if(judget(i,t.num)){
	      y.num=bian(i,t.num); 
	      y.t=g[i].t+t.t;
		  Q.push(y);
	   }
	}
	while(!Q.empty()) Q.pop();
	if(f){ maxt=t.t; return true; }
	else return false;
}
int main()
{
	int i,j,num=0;
    char str[22];
	while(scanf("%d%d",&n,&m)==2){
	   if(n==0&&m==0)break;
	   for(i=0;i<m;i++){
	     scanf("%d%s",&g[i].t,str);
		 g[i].f[0]=g[i].f[1]=g[i].b[0]=g[i].b[1]=0;
		 for(j=0;j<n;j++){  if(str[j]=='+') g[i].f[0]+=(1<<j); if(str[j]=='-') g[i].f[1]+=(1<<j);  }
	     scanf("%s",str);
		 for(j=0;j<n;j++){  if(str[j]=='+') g[i].b[0]+=(1<<j); if(str[j]=='-') g[i].b[1]+=(1<<j);  }
	   }
	   for(i=0;i<(1<<n);i++){mark[i]=false; }
	   printf("Product %d\n",++num);
	   if(bfs()) printf("Fastest sequence takes %d seconds.\n\n",maxt);
	   else printf("Bugs cannot be fixed.\n\n");
	}
	return 0;
}


 


#include<cstdio>/*差了两秒 看来写程序在时间允许的情况下应该 看看考虑怎样将程序进行优化*/
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
const int maxv=2147483647;
struct node{
   int t;
   char s[2][22];
}g[105];
struct bug{
  int num, t;
  bool operator<(const bug &A)const{
    return t>A.t;
  }
};
int d[1<<20];
bool mark[1<<20];
int n,m,maxt;
bool judget(int a,int x){
    int k,h=x;
	for(int i=0;i<n;i++) if(g[a].s[0][i]=='+') {
	    k=(h&(1<<i));	
		if(0==k)return false; }
	else if(g[a].s[0][i]=='-') {
		  k=(h&(1<<i)); 
		if(k!=0) return false; 
	}
	return true;
}
int bian(int a,int x){
  int h=x,k;
  for(int i=0;i<n;i++)if(g[a].s[1][i]=='+') {
	  k=(h&(1<<i));
	  if(0==k)h+=(1<<i); }
	else if(g[a].s[1][i]=='-') { 
		k=h&(1<<i);
		if(k) h-=(1<<i); 
	}
  return h;
}
bool bfs(){
    priority_queue<bug>Q;
    bug t,y;
	bool f=0;
	t.num=(1<<n)-1;t.t=0; Q.push(t);
	while(!Q.empty()){
	   t=Q.top();Q.pop();
	   if(mark[t.num]) continue;
	   mark[t.num]=true;
	   if(t.num==0){ f=1; break;  }
	   for(int i=0;i<m;i++)if(judget(i,t.num)){
	      y.num=bian(i,t.num); 
		  if(mark[y.num]) continue;
	      y.t=g[i].t+t.t;
		  Q.push(y);
	   }
	}
	while(!Q.empty()) Q.pop();
	if(f){ maxt=t.t; return true; }
	else return false;
}
int main()
{
	int i,j,num=0;
    char str[22];
	while(scanf("%d%d",&n,&m)==2){
	   if(n==0&&m==0)break;
	   for(i=0;i<m;i++){
        scanf("%d%s%s",&g[i].t,g[i].s[0],g[i].s[1]);
	   }
	   for(i=0;i<(1<<n);i++){mark[i]=false; }
	   printf("Product %d\n",++num);
	   if(bfs()) printf("Fastest sequence takes %d seconds.\n\n",maxt);
	   else printf("Bugs cannot be fixed.\n\n");
	}
	return 0;
}
#include<cstdio>//uva 10099
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
const int maxv=2147483647;
int e[105][105];
int d[105];
bool inq[105];
int minv(int a,int b){
	return a>b?b:a;
}
int main()
{
    int i,j,n,m,num=0,k;
	while(scanf("%d%d",&n,&m)==2){
	 if(n==0&&m==0) break;
	  for(i=1;i<=n;i++)
		  for(j=1;j<=n;j++) e[i][j]=0;
		  for(i=0;i<m;i++){
		    int a,b,d;
			scanf("%d%d%d",&a,&b,&d);
			e[b][a]=e[a][b]=d;
		  }
		  int s,d,t;
		  scanf("%d%d%d",&s,&d,&t);
          for(k=1;k<=n;k++)
			  for(i=1;i<=n;i++)
				  for(j=1;j<=n;j++)
				   e[i][j]=e[i][j]>minv(e[i][k],e[k][j])?e[i][j]:minv(e[i][k],e[k][j]);
				  int sum=0;
				  while(t>0){
				     t=t-e[s][d]+1; sum++;
				  }				  
	  printf("Scenario #%d\n",++num);
	  printf("Minimum Number of Trips = %d\n\n",sum);
	}
	return 0;
}
#include<cstdio>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
const int maxv=2147483647;
int next[100005],w[100005],v[100005],first[105];
int n,kk,c[10],t[105],num,N;
char str[10000];
void bian(){
  int i=0,L=0;num=0;
  int len=strlen(str);
  for(i=0;i<len;i++){
      if(str[i]>='0'&&str[i]<='9'){ L=L*10+str[i]-'0'; }
	  else {  t[num++]=L;L=0;}
  }
  t[num++]=L;
}
void add(int a,int b,int y){
	int L=a-b;  if(L<0) L=-L;
       next[N]=first[a];
	   first[a]=N;
	   v[N]=b; 
	   w[N]=L*y;
	   N++;
	   next[N]=first[b];
	   first[b]=N;
	   v[N]=a;
	   w[N]=L*y;
	   N++;
}
void builde(){
     int i,k,j;
	 getchar();
	 for(i=0;i<n;i++){
	   gets(str);
	    bian();
		for(j=0;j<num;j++)
			for(k=j+1;k<num;k++) 
				add(t[j],t[k],c[i]);
	 }
}
int main()
{
	int i,j;
	bool inq[101];
	int d[101];
	while(scanf("%d%d",&n,&kk)==2){
       N=0;
		for(i=0;i<n;i++)
			scanf("%d",&c[i]);
		for(i=0;i<101;i++){first[i]=-1;d[i]=maxv;};
		builde();
        memset(inq,false,sizeof(inq));
       	queue<int>Q;Q.push(0);
		d[0]=0;
		while(!Q.empty()){
		  int x=Q.front();Q.pop();
		  inq[x]=false;
		  for(int e=first[x];e!=-1;e=next[e])
			  if(d[v[e]]>d[x]+60+w[e]){
		    d[v[e]]=d[x]+60+w[e];
			if(!inq[v[e]]){
			 inq[v[e]]=true;
			 Q.push(v[e]);
			}
		  }
		}
		if(d[kk]==maxv)printf("IMPOSSIBLE\n");
		else if(kk!=0) printf("%d\n",d[kk]-60);
		else printf("0\n");
	}
	return 0;
}

 

#include<cstdio>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
const int maxv=2147483647;
int first[20005],next[100005],v[100005],w[100005],N;
int  n,m,s,dd,d[20005];
bool inq[20005];
void add(int a,int b,int q){
	next[N]=first[a];
	first[a]=N;
	v[N]=b;
	w[N]=q;
	N++;
	next[N]=first[b];
	first[b]=N;
	v[N]=a;
	w[N]=q;
    N++;
}
int main()
{
	int t,i,num=0;
	scanf("%d",&t);
    while(t--){
	    N=0;
		scanf("%d%d%d%d",&n,&m,&s,&dd);
		for(i=0;i<n;i++){d[i]=maxv; first[i]=-1; inq[i]=false;}
		for(i=0;i<m;i++){
		  int a,b,q;
		   scanf("%d%d%d",&a,&b,&q);
		   add(a,b,q);
		}
		queue<int>Q;
	    d[s]=0;
		Q.push(s);
		while(!Q.empty()){
		  int x=Q.front();Q.pop();
		  inq[x]=false;
		  for(int e=first[x];e!=-1;e=next[e])if(d[v[e]]>d[x]+w[e]){
		      d[v[e]]=d[x]+w[e];
              if(!inq[v[e]]){
			    inq[v[e]]=true;
				Q.push(v[e]);
			  }
		  }		
		}
		if(d[dd]==maxv)printf("Case #%d: unreachable\n",++num);
		else printf("Case #%d: %d\n",++num,d[dd]);

	}
	return 0;
}


 


 

#include<cstdio>
#include<string.h>/*用spaf 判断是否存在 负环*/
#include<iostream>
#include<queue>
using namespace std;
const int maxn=1005;
const int maxm=2005;
const int maxv=2147483647;
int first[maxn],next[maxm],w[maxm],v[maxm],d[maxn],N,num[maxn];
bool inq[maxn];
void add(int a,int b,int t){
   next[N]=first[a];
   first[a]=N;
   w[N]=t;
   v[N]=b;
   N++;
}
int main(){
   
	int t,n,m,i;
	scanf("%d",&t);
	while(t--){
		N=0;
	   scanf("%d%d",&n,&m);
	   for(i=0;i<n;i++){inq[i]=false; first[i]=-1;d[i]=maxv;num[i]=0;}
	   for(i=0;i<m;i++){
	     int a,b,t;
		 scanf("%d%d%d",&a,&b,&t);
		 add(a,b,t);
	   }
	   bool flag=false;
	   queue<int>Q;
	   Q.push(0);d[0]=0;
	   while(!Q.empty()){
	     int x=Q.front(); Q.pop();
		 inq[x]=false;
		 num[x]++;
		 if(num[x]>n) {flag=true;  break; }
		 for(int e=first[x];e!=-1;e=next[e])
			 if(d[v[e]]>d[x]+w[e]){
			    d[v[e]]=d[x]+w[e];
				if(!inq[v[e]]){
				  inq[v[e]]=true;
				  Q.push(v[e]);
				}
			 }
	   
	   }
	   if(flag) printf("possible\n");
	   else printf("not possible\n");
	}

  return 0;
}


 

      题目说的是 给了m个 数组 啊是,s,n,o,k     o是大于小于号
      在 s 到 s+n 这段区间内 和小于k或者大于k 判断是否这样的 序列数存在
      然后可以 列出 这样的 不等式
      把下标小的放在 前面 下标大的放在后面
      当是大于号时
      s[b]-s[a-1]>=k+1;
      当是小于号时
      s[a-1]-s[b]>=-k+1;
      A-B>=C 时从B建一条边 到A 权值为 C 然后就 进行最长路
      要每个曾经出现过的点都要进行一次最长路 
      因为我们不知道默认的 s[i] 和s[i-1]之间的关系  
      因此只能进行枚举一旦出现正环便是无解

   

 

#include<iostream>
#include<cstdio>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=10000;
const int maxm=105;
const int maxv=2147482647;
struct edg{
  int a,b,w,h;
}e[maxn];
int  next[maxn],p[maxm],w[maxn],v[maxn],n,m,d[maxm],en,ma,mi,tim[maxm];
bool mark[maxm],inq[maxm];
void add(int a,int b,long long  c){
     next[en]=p[a];  p[a]=en; v[en]=b;w[en]=c; en++;
}
queue<int>Q;
void inti(){
   for(int i=mi-1;i<=ma;i++){
     inq[i]=false;
     d[i]=-maxv; tim[i]=0;
   }
   while(!Q.empty()) Q.pop();
}
bool spfa(int x){
    inti();
    d[x]=0;
    Q.push(x);
    tim[x]++;
    bool f=false;
    while(!Q.empty()){
        int t=Q.front(); Q.pop();
        inq[t]=false;
        for(int i=p[t];i!=-1;i=next[i])
            if(d[v[i]]<d[t]+w[i]){
               d[v[i]]=d[t]+w[i];
               if(!inq[v[i]]){
                  inq[v[i]]=true;
                  Q.push(v[i]);
                  tim[v[i]]++;
                  if(tim[v[i]]>en){
                     f=true; break;
                  }
               }
            }
        if(f) break;
    }
    return f;
}
int main()
{
    char str[5];
    while(true){
            en=0;
            ma=0;mi=2000000;
         scanf("%d",&n); if(n==0) break;
         scanf("%d",&m);
         memset(mark,false,sizeof(mark));
         for(int i=0;i<m;i++){
            scanf("%d%d%s%d",&e[i].a,&e[i].b,str,&e[i].w);
             e[i].b=e[i].b+e[i].a;
             if(e[i].a>=e[i].b) { int te=e[i].a;e[i].a=e[i].b;e[i].b=te; }
             if(ma<e[i].b) ma=e[i].b;
             if(mi>e[i].a) mi=e[i].a;
             mark[e[i].a]=true; mark[e[i].b]=true;
            if(str[0]=='g') e[i].h=1;
            else e[i].h=-1;
         }
         memset(p,-1,sizeof(p));
         for(int i=0;i<m;i++)
            if(e[i].h>0)
              add(e[i].a-1,e[i].b,e[i].w+1);
            else add(e[i].b,e[i].a-1,-e[i].w+1);
        bool f=false;
        for(int i=mi;i<=ma;i++)
            if(mark[i]){

            if(spfa(i-1))  {
                f=true; break;
            }
        }
        if(f) printf("successful conspiracy\n");
        else printf("lamentable kingdom\n");


    }
    return 0;
}


 


这题刚开始用了spfa 一直 wa 到不行看看题目 嗨!题目 没说要转移次数相同时
   要取最大值 这就是 spfa 错的 原因 
   来个 Floyd 就解决的 好神奇  题目也有点小坑 不说清楚来


 

#include <iostream>
#include <cstdio>
#include<string.h>
#include<stack>
using namespace std;
const int maxn=25;
int F[maxn][maxn][maxn];
double D[maxn][maxn][maxn];
int main()
{
     int n;
     while(scanf("%d",&n)==1){
            memset(D,0,sizeof(D));
         for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
             if(i==j) D[i][j][1]=1;
             else scanf("%lf",&D[i][j][1]);
             F[i][j][1]=-1;
            }
        for(int t=2;t<=n;t++){
            for(int k=1;k<=n;k++)
                for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                 if(D[i][j][t]<D[i][k][t-1]*D[k][j][1]){
                    D[i][j][t]=D[i][k][t-1]*D[k][j][1];
                    F[i][j][t]=k;
                 }
        }
        int L=-1,J=-1;
       for(int K=2;K<=n;K++){
        for(int  i=1;i<=n;i++ )
           if(D[i][i][K]>1.01){
             L=i; J=K;
             break;
        }
        if(L!=-1) break;
       }
       if(L==-1) {
         printf("no arbitrage sequence exists\n"); continue;
       }
       stack<int>T;
       T.push(L);
       int R=F[L][L][J];
       while(R!=-1){
         T.push(R);
         J--;
         R=F[L][R][J];
       }
       printf("%d",L);
       while(!T.empty()){
          int G=T.top();  T.pop(); printf(" %d",G);
       }
       printf("\n");
     }
    return 0;
}


 


 

uva 125
/*
    uva 125 这题说的是  在n个交叉路口之间 让你计算出 有几条路径 
	存在环的 就 输出-1 
	 floy 加上自己编的 判断环和环所能到达的点

*/
#include <iostream>
#include<cstdio>
#include<string.h>
using namespace std;
int next[1000],p[35],v[1000],ednum,n,num[35][35],e[35][35];
int fi[35],loop[35];
void add(int a,int b){
    next[ednum]=p[a]; v[ednum]=b; p[a]=ednum; ednum++;
}
void dfs(int a){
     for(int e=p[a];e!=-1;e=next[e]){
         if(fi[v[e]]==2){
            loop[v[e]]=1; continue;
        }
        if(fi[v[e]]==1) continue;
        fi[v[e]]=2;
        dfs(v[e]);
        fi[v[e]]=1;
     }
}
void solve(int a){
     int D=loop[a];
     for(int e=p[a];e!=-1;e=next[e])
     {
         int b=v[e];
         if(D==0&&fi[b]==1) continue;
         if(D==1&&fi[b]==1&&loop[b]==1) continue;
         if(D==1) loop[b]=1;
         fi[b]=1;   solve(b);
     }

}
int main()
{
    int ma,G=0,i,j,k;
     while(scanf("%d",&n)==1){
          ma=0;
          ednum=0;
          memset(e,0,sizeof(e));
          memset(num,0,sizeof(num));
           memset(p,-1,sizeof(p));
           for( i=0;i<n;i++){
              int a,b;
			  scanf("%d%d",&a,&b);
			  int c=a>b?a:b;
			  if(ma<c)ma=c;
             num[a][b]=1;
             add(a,b);
           }
           for( k=0;k<=ma;k++)
            for( i=0;i<=ma;i++)
            for( j=0;j<=ma;j++)
           if(num[i][k]!=0&&num[k][j]!=0){
              num[i][j]+=num[i][k]*num[k][j];
           }
           printf("matrix for city %d\n",G++);
           for( i=0;i<=ma;i++){
             memset(loop,0,sizeof(loop)); memset(fi,0,sizeof(fi));
             fi[i]=2;
             dfs(i);
             memset(fi,0,sizeof(fi));
             fi[i]=2;
             solve(i);
             for( j=0;j<ma;j++)
                if(loop[j]==0) printf("%d ",num[i][j]);
             else printf("-1 ");
             if(loop[ma]==0) printf("%d\n",num[i][ma]);
             else printf("-1\n");
           }

     }
    return 0;
}


 



 

/*
    uva 10803 计算从任何一个点到图中的另一个点经历的途中必须每隔10千米 都必须有一个点
    然后就这样 floy 及解决了 
*/
#include <iostream>
#include<cstdio>
#include<string.h>
#include<cmath>
using namespace std;
const double maxv=1.79769e+308;
struct point{
 double x,y;
}T[105];
double e[102][102];
int dcmp(double a){
   if(fabs(a)<0.00000001) return 0;
   if(a>0) return 1;
   else return -1;
}
double dist(int a,int b){
   return sqrt((T[a].x-T[b].x)*(T[a].x-T[b].x)+(T[a].y-T[b].y)*(T[a].y-T[b].y));
}
int main()
{
    int n,H=0,Tt;
    bool inq[105];
     scanf("%d",&Tt);
    while(Tt--){
            scanf("%d",&n);
         printf("Case #%d:\n",++H);
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&T[i].x,&T[i].y);
            for(int j=0;j<=i;j++){
                double t=dist(i,j);
                if(dcmp(10-t)<0) e[i][j]=e[j][i]=maxv;
                 else e[i][j]=e[j][i]=t;
            }
        }
        for(int k=0;k<n;k++)
            for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
            if(e[i][k]<maxv&&e[k][j]<maxv&&e[i][j]>e[i][k]+e[k][j]){
                e[i][j]=e[i][k]+e[k][j];
            }
            double ma=0;
        for(int i=0;i<n;i++)
            for(int j=i;j<n;j++)
            if(dcmp(e[i][j]>ma)>0) ma=e[i][j];
        if(dcmp(ma-maxv)==0) printf("Send Kurdy\n");
        else printf("%.4lf\n",ma);
         // if(Tt!=0)
          printf("\n");
    }
    return 0;
}


 




 

uva 11045
这题说的是 每种 T恤都 是n/6种 看是否 能满足 所有的 自愿者的要求 就是每个自愿者最多 一件 
然 后 建一条 边 原点 到 各种 大小 建一条 每个人到 汇点建一个

#include <iostream>
#include<cstdio>
#include<string.h>
#include<queue>
using namespace std;
const int maxv=2147483647;
const int maxn=350;
const int maxno=100;
struct flow_EK{
     int cap[maxno][maxno],flow[maxno][maxno],next[maxn],p[maxno],v[maxn],ednum,H,per[maxno];
     queue<int>Q;
     void inti(){
       memset(cap,0,sizeof(cap)); memset(flow,0,sizeof(flow)); memset(p,-1,sizeof(p));H=ednum=0;
     }
     void add(int a,int b,int c){
         next[ednum]=p[a]; p[a]=ednum;
         v[ednum]=b; ednum++;
         next[ednum]=p[b];p[b]=ednum;
         v[ednum]=a; ednum++;
         cap[a][b]=c; cap[b][a]=0;
     }
     void EK(int st,int en){
         while(!Q.empty())Q.pop();
         while(true){
            memset(per,-1,sizeof(per));
            Q.push(st); per[st]=100000;
            while(!Q.empty()){
                int x=Q.front();Q.pop();
                for(int e=p[x];e!=-1;e=next[e]){
                    int to=v[e];
                    if(per[to]==-1&&cap[x][to]>flow[x][to]){
                        per[to]=x; Q.push(to);
                    }

                }
            }
            int ma=maxv;
            if(per[en]==-1) break;
            for(int e=en;e!=st;e=per[e])
                ma=ma<cap[per[e]][e]-flow[per[e]][e]?ma:cap[per[e]][e]-flow[per[e]][e];
            for(int e=en;e!=st;e=per[e]){
                flow[per[e]][e]+=ma;
                flow[e][per[e]]-=ma;
            }
            H+=ma;
         }

     }

}T;
char str[10][6]={ {"XXL"},{"XL"},{"L"},{"M"},{"S"},{"XS"}   };
char s[2][5];
int FI(int a){
  for(int i=0;i<6;i++)
    if(strcmp(str[i],s[a])==0) return i;
    return 0;
}
int main()
{
    int n,m,t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        T.inti();
        T.add(m+7,m+6,n);
        for(int i=0;i<6;i++)
            T.add(m+6,m+i,n/6);
        for(int i=0;i<m;i++){
            scanf("%s%s",s[0],s[1]);
            int a=FI(0)+m,b=FI(1)+m;
            T.add(a,i,1);T.add(b,i,1);
            T.add(i,m+8,1);
        }
          T.EK(m+7,m+8);
        if(T.H==m)printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}


 



#include <iostream> 这题说的是 线将戒指连在一起然后人选两个使得最多的线被拉直floy加是记忆化搜索  记得有些戒指并不在线上 我就是这里没考虑呢wa了几次
#include<cstdio>
#include<string.h>
#include<queue>
using namespace std;
const int maxv=2147483647;
int e[125][125],ednum,p[125],d[125];
bool inq[125];
struct edg{
 int to,nex;
}E[14500];
void add(int a,int b){
    E[ednum].to=b; E[ednum].nex=p[a];p[a]=ednum; ednum++;
    E[ednum].to=a; E[ednum].nex=p[b];p[b]=ednum; ednum++;
}
int dfs(int ma,int st,int en,int step){

       if(ma==step){
          if(st==en) return 1; else return 0;
       }
       if(d[st]!=-1) {
          if(d[st]==step) return 1;
          else return 0;
       }
       int sum=0;
       for(int e=p[st];e!=-1;e=E[e].nex){
             int to=E[e].to;
             if(inq[to]) continue;
             inq[to]=true;
             int s=dfs(ma,to,en,step+1);
             if(s!=0&&d[st]==-1) d[st]=step;
             sum+=s;
             inq[to]=false;
       }
       if(sum!=0) return sum+1;
       return sum;
}
int main()
{
     int t;
     scanf("%d",&t);
     for(int cad=1;cad<=t;++cad)
     {
         int n,m;  ednum=0;
         scanf("%d%d",&n,&m);
         memset(p,-1,sizeof(p));
         for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
             e[i][j]=i==j?0:maxv;
         for(int i=0;i<m;i++){
             int a,b;
             scanf("%d%d",&a,&b);
             e[a][b]=e[b][a]=1;
             add(a,b);
         }
         for(int k=0;k<n;k++)
            for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
             if(e[i][k]!=maxv&&e[k][j]!=maxv)
              e[i][j]=e[i][j]>(e[i][k]+e[k][j])?(e[i][k]+e[k][j]):e[i][j];
         int ma=0;
          for(int i=0;i<n;i++)
          for(int j=i+1;j<n;j++)
            if(e[i][j]!=maxv){
                ma=ma<e[i][j]?e[i][j]:ma;
            }
            int F=0;
           for(int i=0;i<n;i++)
           for(int j=i+1;j<n;j++)
           if(ma==e[i][j]){
              memset(d,-1,sizeof(d));
              memset(inq,false,sizeof(inq));
              inq[i]=true;
               int G=0;
               for(int e=p[i];e!=-1;e=E[e].nex){
                     if(d[E[e].to]!=-1) continue;
                      inq[E[e].to]=true;
                     G+=dfs(ma,E[e].to,j,1);
                      inq[E[e].to]=false;
                 }
               if(G>F) F=G;
              inq[i]=false;
           }
         printf("Case #%d: %d\n",cad,F);
     }
    return 0;
}
#include <iostream>/* 简单并查集 说的是最大的团体是朋友的人数是多少*/
#include<cstdio>
#include<string.h>
int d[30000],p[30005],ma;
int findf(int a){
   return p[a]=p[a]==a?a:findf(p[a]);
}
void uniFA(int a,int b){
    int fa=findf(a), fb=findf(b);
    if(fa==fb)return ;
    p[fa]=fb;
    d[fb]=d[fa]+d[fb];
    if(d[fb]>ma) ma=d[fb];
}
int main()
{
     int t,n,m;
     std::cin>>t;
     while(t--){
            ma=1;
        std::cin>>n>>m;
        for(int i=0;i<=n;i++){
             p[i]=i; d[i]=1;
        }
        for(int i=0;i<m;i++){
             int a,b;
             std::cin>>a>>b;
             uniFA(a,b);
        }
        std::cout<<ma<<'\n';
     }
    return 0;
}
#include <iostream>/*说的是给了你很多人的关系其中有两个国家的人然后进行四种操作  1
  1 将A和B 设为朋友
  2 将A和B 设为敌人
  3 判断A和B是朋友吗
  4 判断A和B是敌人吗
  如果出现 相矛盾的 设置就 输出-1 忽略这次操作
  如果对于3 4 的判断出现相应的 输出1 否则0 ;
*/
#include<cstdio>
#include<string.h>
using namespace std;
const int maxn=10005;
int per[maxn],D[maxn];
int fa(int a){
  return per[a]=per[a]==a?a:fa(per[a]);
}
void solve1(int a,int b){
    int pa=fa(a),pb=fa(b);
    if(D[pa]==pb){  printf("-1\n"); return ;}
    if(D[pa]==-1&&D[pb]==-1){
        per[pb]=pa; return ;
    }
    if(D[pa]!=-1&&D[pb]==-1){
       per[pb]=pa;return  ;
    }
    if(D[pa]==-1&&D[pb]!=-1){
        per[pa]=pb; return ;
    }
    int dpa=fa(D[pa]),dpb=fa(D[pb]);
    per[pb]=pa; per[dpb]=dpa;
}
void solve2(int a,int b){
    int pa=fa(a),pb=fa(b);
    if(pa==pb){  printf("-1\n"); return;}
    if(D[pa]==-1&&D[pb]==-1){
        D[a]=b; D[b]=a;
        per[pa]=a; per[pb]=b; per[a]=a; per[b]=b; return ;
    }
    if(D[pa]==-1&&D[pb]!=-1){
        int dpb=fa(D[pb]);
         per[pa]=dpb; return ;
    }
    if(D[pa]!=-1&&D[pb]==-1){
        int dpa=fa(D[pa]);
         per[pb]=dpa; return ;
    }
    int dpa=fa(D[pa]),dpb=fa(D[pb]);
    per[a]=a; per[b]=b;
    per[dpb]=a; per[dpa]=b;
    per[pa]=a;per[pb]=b;
    D[a]=b;D[b]=a;
}
void solve3(int a,int b){
    int pa=fa(a),pb=fa(b);
    if(pa==pb)printf("1\n");
    else printf("0\n");
}
void solve4(int a,int b){
   int pa=fa(a),pb=fa(b);
   if(D[pa]==pb) printf("1\n");
   else printf("0\n");
}
int main()
{
    int n;
    while(scanf("%d",&n)==1){
         for(int i=0;i<=n;i++){
            D[i]=-1; per[i]=i;
         }
        int a,b,c;
        while(true){
            cin>>c>>a>>b;
            if(c==0) break;
            switch(c){
              case 1: solve1(a,b); break;
              case 2: solve2(a,b); break;
              case 3: solve3(a,b); break;
              case 4: solve4(a,b); break;
            }

        }
    }
    return 0;
}
#include <iostream>
/*
这题说的是 超级玛丽 救到了公主后返回家中  他们在城堡 A+B 他家在 1 (补充一下 有A 个乡村
B 座城堡,编号前A个是乡村) 超级玛丽有一双魔法鞋 他遇到城堡必须停下了 遇到村庄可以不停下了
但是这双鞋只可以在乡村或者城堡停或者开始走 用这双鞋可以不花费任何时间从一个点到另一个点
如果这两个点之间有路的话,然后规定这双鞋子一次只能走不超过 L米 不能用超过K次 然后计算从城堡
A+B 到达家1 的最短时间(一单位代表一单位时间) 
我刚开始想用网络流 发现不怎么可能 建不了图 流量也不知道怎么设置 
想想 可以知道的是在乡村与乡村之间是可以跨乡村的使用鞋子
然后就用floy计算出每两个乡村之间的距离
然后在城堡之间可能也能跨乡村的使用鞋子 i j 为城堡 k为乡村 可能dp[i][j]=dp[i][k]+dp[k][j]
这也是可以用鞋子直接飞过来的  然后这些处理好之后 就在此想有什么用
可以知道对于每个点可能是经过m次的使用鞋子后到达的 突然知道了 
对于每个点可能有k种状态 d[i][k]就是说他是通过几次使用鞋子到达的得到转移方程
d[j][k]=(d[i][k-1],d[i][k]+d[i][j])
解答完毕了
*/
#include<cstdio>
#include<string.h>
using namespace std;
const int maxv=2147483647;
const int maxn=103;
int dp[maxn][maxn],d[maxn][15];
int minv(int a,int b){  return a>b?b:a; }
int main()
{
    int t,A,B,M,L,K;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d%d%d",&A,&B,&M,&L,&K);
        for(int i=0;i<=A+B;i++)
            for(int j=0;j<=A+B;j++)
             dp[i][j]=i==j?0:maxv;
        for(int i=0;i<=A+B;i++)
            for(int j=0;j<=K+1;j++)
              d[i][j]=maxv;
        for(int i=0;i<M;i++){
             int a,b,H;
             scanf("%d%d%d",&a,&b,&H);
             dp[a][b]=dp[b][a]=H;
        }
        for(int k=1;k<=A;k++)
            for(int i=1;i<=A;i++)
             for(int j=1;j<=A;j++)
             if(dp[i][k]!=maxv&&dp[k][j]!=maxv)
              dp[i][j]=dp[i][j]>dp[i][k]+dp[k][j]?dp[i][k]+dp[k][j]:dp[i][j];
        for(int i=1;i<=A+B;i++)
        for(int j=1;j<=A+B;j++)
         for(int k=1;k<=A;k++)
          if(dp[i][k]!=maxv&&dp[k][j]!=maxv)
           dp[i][j]=dp[i][j]>dp[i][k]+dp[k][j]?dp[i][k]+dp[k][j]:dp[i][j];
          d[A+B][1]=0;
        for(int k=1;k<=K+1;k++)
             for(int T=0;T<A+B;T++)
             for(int i=1;i<=A+B;i++){
              if(d[i][k-1]==maxv&&d[i][k]==maxv) continue;
              for(int j=1;j<=A+B;j++){
                    if(dp[i][j]==maxv) continue;
                  int LJ=(d[i][k-1]==maxv||dp[i][j]>L)?maxv:d[i][k-1];
                  int RJ=(d[i][k]==maxv||dp[i][j]==maxv)?maxv:d[i][k]+dp[i][j];
                  d[j][k]=minv(d[j][k],minv(LJ,RJ));
              }
        }
            int ma=maxv;
            for(int i=1;i<=K+1;i++)
                 ma=ma>d[1][i]?d[1][i]:ma;
            printf("%d\n",ma);
    }
    return 0;
}
#include <iostream>
/*
这题放在图论这一块我不知道是为什么可能是我没找到正确的解法吧
这题说的是给了 n头牛T 天的产量  每头牛都用这个周期去产奶计算
一天当中产奶最少的那头牛将会被杀 如果有多头牛产奶同样最少就
不会被杀 问最后有 几头牛被杀 还有最后被杀的那头牛是哪天被杀的
我用模拟的方法 用链表去存贮还没被杀的牛 然后每次发现有头牛被杀
就将他从链表中删掉然后 重新计算过周期 若在一个周期内没有一头被杀
那么将来就不会有牛被杀了 
*/
#include<cstdio>
#include<string.h>
using namespace std;
const int maxn=1000;
struct node{
  int fir,nex,h;
}P[1000];
int n,T[maxn][15];
int gcd(int a,int b){
   if(b==0) return a;
   return gcd(b,a%b);
}
int H(){
    int L=P[0].nex;
    int G=1;
   while(L!=0){
      int F=gcd(G,P[L].h);
      G=G*P[L].h/F;
      L=P[L].nex;
   }
   return G;
}
int main()
{
     int t;
     scanf("%d",&t);
     while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
             scanf("%d",&P[i].h);
             for(int j=0;j<P[i].h;j++)
                scanf("%d",&T[i][j]);
             P[i-1].nex=i; P[i].fir=i-1;
        }
        P[n].nex=0;P[0].fir=n;

        int K=H(),lastti=0,killniu=n;
        for(int i=0;i<K;i++){
            int mi=2147483647,num=0,loca;
            int L=P[0].nex;
            while(L!=0){
              int  N=P[L].h;
                N=i%N;
                if(T[L][N]<mi){ num=1;mi=T[L][N] ;loca=L;}
                else if(T[L][N]==mi){ num++; }
                L=P[L].nex;
            }
            if(num==1){
                lastti=i;--killniu;
                int fir=P[loca].fir,nex=P[loca].nex;
                P[fir].nex=nex; P[nex].fir=fir;
                if(P[0].nex==0)break;
                K=H()+i+1;
            }

        }

        printf("%d %d\n",killniu,lastti==0?lastti:lastti+1);
     }
    return 0;
}

 
posted @ 2014-04-08 20:54  来自大山深处的菜鸟  阅读(147)  评论(0编辑  收藏  举报