做了十来道了,基本都挺水的,主要自己傻,各种数组开小,RE了不少
zoj 1586
题意:貌似就是说给出了许多QS之间的路,然后QS每次只能用一次(每次都有花费)
题解:就是边的权值还得加上两点的花费(都是题意难以理解)
for(int i=1;i<=n;i++){ scanf("%d",&val[i]); pre[i]=i; } int xcount=0; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ int a; scanf("%d",&a); if(j>=i) continue; p[xcount].u=i; p[xcount].v=j; p[xcount++].w=a+val[i]+val[j]; } } sort(p,p+xcount); int sum=0; for(int i=0;i<xcount;i++){ int a=p[i].u; int b=p[i].v; int aa=Find(a); int bb=Find(b); if(aa!=bb){ pre[aa]=bb; sum+=p[i].w; } }
题意:给你n条字符串,每个字符串长为7,然后如果两个字符串之间同一位置字符不同的个数就是字符串的距离
题解:每次输入的时候都计算下距离,然后kruskal,好像当时脑残了数组开小了,RE了半天
for(int i=1;i<=n;i++){ pre[i]=i; scanf("%s",s[i]); int len=strlen(s[i]); for(int j=1;j<i;j++){ int num=0; for(int k=0;k<len;k++){ if(s[i][k]!=s[j][k]) num++; } p[xcount].u=i; p[xcount].v=j; p[xcount++].w=num; } } sort(p,p+xcount); int sum=0; for(int i=0;i<xcount;i++){ int a=p[i].u; int b=p[i].v; int aa=Find(a); int bb=Find(b); if(aa!=bb){ pre[aa]=bb; sum+=p[i].w; } } printf("The highest possible quality is 1/%d.\n",sum);
题意:给你s个卫星,p个村庄,然后村庄之间通讯,有卫星的村庄可以不花费(我开头以为是一个卫星可以对应一条路,原来是一个卫星对应一个村庄)
题解:最小生成树,权值最大的s-1条边就用卫星(s个村庄有卫星),就是只要连n-s条边就能break了
for(int i=1;i<=s;i++){ pre[i]=i; double x,y; scanf("%lf%lf",&node[i].x,&node[i].y); for(int j=1;j<i;j++){ double r=node[i].x-node[j].x; double s=node[i].y-node[j].y; double dis=sqrt(r*r+s*s); p[xcount++]=(Edge){i,j,dis}; } } sort(p,p+xcount); double maxn=0; int cnt=0; for(int i=0;i<xcount;i++){ int a=p[i].u; int b=p[i].v; int aa=Find(a); int bb=Find(b); if(aa!=bb){ pre[aa]=bb; cnt++; maxn=maxn<p[i].w?p[i].w:maxn; } if(cnt==s-n) break; } printf("%.2f\n",maxn);
题意:给你个迷宫,#是不能走,空格可以走,AS是几个目的地,可以看成点,然后就是这些点连起来最小花费
题解:显然kruskal,不过需要bfs算出每个点到别的点的权值,G++会T,C++能过,还有个天坑就是每行都有空格,要用gets,然后开头x,y输入完了之后后面也有空格,不能用getchar吃个回车,要用gets再吃个一行
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; #define MAX 300+5 #define MAXN 100000+5 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define mid int m=l+(r-l)/2 #define LL long long #define ull unsigned long long #define mem0(x) memset(x,0,sizeof(x)) #define mem1(x) memset(x,-1,sizeof(x)) #define meminf(x) memset(x,INF,sizeof(x)) #define lowbit(x) (x&-x) const int mod = 1000000007; const int prime = 999983; const int INF = 0x3f3f3f3f; const int INFF = 1e9; const double pi = 3.141592653589793; const double inf = 1e18; const double eps = 1e-10; //读入外挂 inline int read_int(){ int ret=0; char tmp; while(!isdigit(tmp=getchar())); do{ ret=(ret<<3)+(ret<<1)+tmp-'0'; }while(isdigit(tmp=getchar())); return ret; } struct Edge{ int u,v,w; bool operator<(const Edge& a)const{ return w<a.w; } }p[100005]; int pre[MAX]; char maze[MAX][MAX]; int vis[MAX][MAX]; int vis1[MAX][MAX]; int step[MAX][MAX]; int cnt; int x,y; int dx[5]={1,-1,0,0}; int dy[5]={0,0,1,-1}; bool inside(int xx,int yy){ if(xx<0||yy<0||xx>=y||yy>=x) return false ; return true; } int Find(int x){ return pre[x]==x?x:pre[x]=Find(pre[x]); } void Union(int a,int b){ pre[Find(a)]=pre[Find(b)]; } void bfs(int i,int j){ mem0(vis1); mem0(step); queue<int> q; q.push(i*1000+j); vis1[i][j]=1; while(!q.empty()){ int x=q.front()/1000; int y=q.front()%1000; q.pop(); for(int k=0;k<4;k++){ int a=x+dx[k]; int b=y+dy[k]; if(inside(a,b)&&vis[a][b]!=-1&&!vis1[a][b]){ step[a][b]=step[x][y]+1; q.push(a*1000+b); vis1[a][b]=1; if(vis[a][b]>0){ p[cnt].u=vis[i][j]; p[cnt].v=vis[a][b]; p[cnt++].w=step[a][b]; } } } } } int main(){ int t; scanf("%d",&t); while(t--){ char temp[50]; scanf("%d%d",&x,&y); mem0(vis); int xcount=1; gets(temp); for(int i=0;i<y;i++){ gets(maze[i]); for(int j=0;j<x;j++){ if(maze[i][j]=='A'||maze[i][j]=='S'){ vis[i][j]=xcount++; } else if(maze[i][j]=='#'){ vis[i][j]=-1; } } } for(int i=1;i<xcount;i++) pre[i]=i; cnt=0; for(int i=0;i<y;i++){ for(int j=0;j<x;j++){ if(vis[i][j]>0){ bfs(i,j); } } } sort(p,p+cnt); int sum=0; int flag=0; for(int i=0;i<cnt;i++){ int a=p[i].u; int b=p[i].v; int aa=Find(a); int bb=Find(b); if(aa!=bb){ flag++; pre[aa]=bb; sum+=p[i].w; } if(flag==xcount-1) break; } printf("%d\n",sum); } return 0; }
题意:给你点和边,求最小生成树是否唯一
题解:先求出最小生成树,把MST的边都标记,然后枚举每次去掉一条,看有没有算出来sum和MST的sum相同的
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; #define MAX 100+5 #define MAXN 100000+5 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define mid int m=l+(r-l)/2 #define LL long long #define ull unsigned long long #define mem0(x) memset(x,0,sizeof(x)) #define mem1(x) memset(x,-1,sizeof(x)) #define meminf(x) memset(x,INF,sizeof(x)) #define lowbit(x) (x&-x) const int mod = 1000000007; const int prime = 999983; const int INF = 0x3f3f3f3f; const int INFF = 1e9; const double pi = 3.141592653589793; const double inf = 1e18; const double eps = 1e-10; //读入外挂 inline int read_int(){ int ret=0; char tmp; while(!isdigit(tmp=getchar())); do{ ret=(ret<<3)+(ret<<1)+tmp-'0'; }while(isdigit(tmp=getchar())); return ret; } struct Edge{ int u,v,w; bool is_MST; bool operator<(const Edge& a)const{ return w<a.w; } }p[100005]; int pre[MAX]; int Find(int x){ return pre[x]==x?x:pre[x]=Find(pre[x]); } void Union(int a,int b){ pre[Find(a)]=pre[Find(b)]; } int main(){ int t; scanf("%d",&t); while(t--){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) pre[i]=i; for(int i=0;i<m;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); p[i]=(Edge){a,b,c,false}; } sort(p,p+m); int sum=0; int cnt=0; for(int i=0;i<m;i++){ int a=p[i].u; int b=p[i].v; int aa=Find(a); int bb=Find(b); if(aa!=bb){ pre[aa]=bb; sum+=p[i].w; p[i].is_MST=true; cnt++; } if(cnt==n-1) break; } int tmp=0; for(int i=1;i<=n-1;i++){ int flag=0; int tot=0; int num=0; for(int j=1;j<=n;j++) pre[j]=j; for(int j=0;j<m;j++){ if(p[j].is_MST){ flag++; if(flag==i) continue; } int a=p[j].u; int b=p[j].v; int aa=Find(a); int bb=Find(b); if(aa!=bb){ num++; pre[aa]=bb; tot+=p[j].w; } } if(tot==sum&&num==n-1){ tmp=1; break; } } if(tmp) printf("Not Unique!\n"); else printf("%d\n",sum); } return 0; }最小生成树还是比较水的,我可能再去练练求MST的个数,还有就是生成树的题