今天下午图论dfs训练赛,5/10,待补,复习了最短路和最小生成树
早上又是一个偷懒的早上
题目 | A | B | C | D | E | F | G | H | I | J |
---|---|---|---|---|---|---|---|---|---|---|
做题情况 | 未做 | 未做 | AC(-3) | AC | 未做 | 未做 | WA(-11) | AC(-1) | AC(-2) | AC(-5) |
A(待补)
B(待补)
C
题意是n个点,m条路,有一条未知的路在维修,求1到n最短路径的最大值。一开始以为是求最长路径,我是个读假题的机器人。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<string> #define inf 0x3f3f3f3f #define mem(k,b) memset(k,b,sizeof(k)) using namespace std; const int maxn=1100; int mp[maxn][maxn],dis[maxn],vis[maxn]; int l,m,n,x,y,w; int pos[maxn]; void dj(int ss) { for(int i=1;i<=n;i++){ vis[i]=0,dis[i]=inf; } dis[1]=0; for(int i=1;i<=n;i++) { int minn=inf;int k=-1; for(int j=1;j<=n;j++){ if(!vis[j]&&dis[j]<minn){ minn=dis[j]; k=j; } } if(minn==inf){ return ; } vis[k]=1; for(int j=1;j<=n;j++){ if(!vis[j]&&dis[k]+mp[k][j]<dis[j]){ dis[j]=dis[k]+mp[k][j]; if(ss){pos[j]=k;} } } } } int main() { while(~scanf("%d%d",&n,&m)){ mem(pos,0);mem(mp,inf); for(int i=0;i<m;i++){ scanf("%d%d%d",&x,&y,&w); if(mp[x][y]>w){ mp[x][y]=mp[y][x]=w; } } dj(1); int maxcost=dis[n]; for(int i=n;i!=1;i=pos[i]) { int t=mp[i][pos[i]]; mp[i][pos[i]]=mp[pos[i]][i]=inf; dj(0); maxcost=max(maxcost,dis[n]); mp[i][pos[i]]=mp[pos[i]][i]=t; } printf("%d\n",maxcost); } return 0; }
D
一道简单的dfs题,做了好像有三四遍了,所以代码就咕咕咕。E(待补)
F(待补)
G(
没有弄明白题意)
因为不知道要干嘛,所以最后贴了一个网上的代码。说起来这道题不知道是我理解错了,还是……
反正不懂,感觉题目很奇怪,可能是自己还很菜。H
读完题,这是道简单的dp,写完一wa,行吧,天天读假题,后来发现就是板子题。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<stack> #include<cmath> using namespace std; #define mem(a,b) memset(a,b,sizeof(a)) #define inf 0x3f3f3f3f #define mod 1000000007 #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) const int maxn=1e5+10; int g[110][110],a[110],vis[110]; int n; int prime(int cur){ int kk, sum = 0; rep(i, 1, n){ a[i] = g[cur][i]; vis[i] = false; } vis[cur] = true; rep(i, 2, n){ int mincost = inf; rep(j, 1, n){ if (!vis[j] && a[j] < mincost){ kk = j; mincost = a[j]; } } vis[kk] = true; sum += mincost; rep(j, 1, n){ if (!vis[j] && a[j] > g[kk][j]){ a[j] = g[kk][j]; } } } return sum; } int main() { while(~scanf("%d",&n)){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ scanf("%d",&g[i][j]); } } printf("%d\n",prime(n)); } return 0; }
I
一开始以为是八皇后问题,然后发现其实就是填充问题,还必须填满。上来裸了一个dfs超时……
然后优化过程中不能出现棋子数量大于n-剩余列数的剪枝
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<stack> #include<cmath> using namespace std; #define mem(a,b) memset(a,b,sizeof(a)) #define inf 0x3f3f3f3f #define mod 1000000007 #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) const int maxn=10; char g[maxn][maxn]; int vis[maxn][maxn],xx[maxn],yy[maxn]; int n,m,maxx,sum; void dfs(int sum,int r) { if(!sum){ maxx++; return; } for(int i=r;i<n;i++){ if(!xx[i] && n>=(sum+i)){ for(int j=0;j<n;j++){ if(!yy[j]){ if(g[i][j]=='#'&& !vis[i][j]){ yy[j]=1;xx[i]=1;vis[i][j]=1; dfs(sum-1,r+1); yy[j]=0;xx[i]=0;vis[i][j]=0; } } } } } } int main() { while(~scanf("%d%d",&n,&m)){ if(n==-1 && m==-1){break;} for(int i=0;i<n;i++){ scanf("%s",g[i]); xx[i]=0,yy[i]=0; } mem(vis,0); maxx=0; dfs(m,0); printf("%d\n",maxx); } return 0; }
J
读完这题我终于明白我应该好好学中文和英语。
一wa这个大妈要走最短的路从1~n
二wa这个大妈可能是要1到(2~n)之间最长的路
最终在wa了四次之后,毅然决然打开百度翻译,哦,原来就是一道最小生成树,这位大妈有个瓶子,每走一米喝一口水,每个点可以把瓶子装满,要瓶子最大能装大妈几口水。
求最短路中的子路径最大即可,写完自信一wa……哦原来x和y写反了,这种细节要注意
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<stack> #include<cmath> using namespace std; #define mem(a,b) memset(a,b,sizeof(a)) #define inf 0x3f3f3f3f #define mod 1000000007 #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) const int maxn=2100; int g[maxn][maxn],a[maxn],vis[maxn]; int n,m; int prime(int cur){ int kk, maxx = -1; rep(i, 1, n){ a[i] = g[cur][i]; vis[i] = false; } vis[cur] = true; rep(i, 2, n){ int mincost = inf; rep(j, 1, n){ if (!vis[j] && a[j] < mincost){ kk = j; mincost = a[j]; } } vis[kk] = true; if(maxx<mincost){ maxx=mincost; } rep(j, 1, n){ if (!vis[j] && a[j] > g[kk][j]){ a[j] = g[kk][j]; } } } return maxx; } int main() { while(~scanf("%d%d",&n,&m)){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(i==j){ g[i][j]=0; } else{ g[i][j]=inf; } } } for(int i=0;i<m;i++){ int x,y,w; scanf("%d%d%d",&x,&y,&w); if(g[x][y]>w){ g[x][y]=g[y][x]=w; } } printf("%d\n",prime(1)); } return 0; }
ps:一定要补题,A题看过好难……E题听王韬韬说是dp,我一定会补的
咕咕咕