https://www.luogu.org/problem/show?pid=3386
二分圖模版題……debug真累
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1001;
int n,m,e;
bool vis[maxn],a[maxn][maxn]={0};//u,v
int shu[maxn]={0};//判斷m中點與n中何點連接
bool dfs(int i){
for(int j=1;j<=m;j++){
if(a[i][j]&&!vis[j]){
vis[j]=1;
if(!shu[j]||dfs(shu[j])){
shu[j]=i;
return 1;
}
}
}
return 0;
}
int main(){
int u,v,ans=0;
scanf("%d%d%d",&n,&m,&e);
for(int i=1;i<=e;i++){
scanf("%d%d",&u,&v);
if(u>n||v>m) continue;
a[u][v]=1;
}
for(int i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
if(dfs(i))ans++;
}
printf("%d",ans);
return 0;
}
順便攢一道題
hdu 3036
未完成
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=10000;
const int INF=2147483640;
struct{
int next;
int to;
int w;
}edge[1000000];
int head[maxn],cnt=-1;
void add(int u,int v,int w){//u起點v終點w容量
cnt++;
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt;
}
int lev[maxn],cur[maxn];//lev層數,cur[i]爲以i爲起點的邊的編號
bool bfs(int m){//強制1爲源點,m爲匯點
int dui[m],r=0;//隊列和右指針
for(int i=1;i<=m;i++){//初始化
lev[i]=-1;
cur[i]=head[i];
}
dui[0]=1,lev[1]=0;
int u,v;//u起點v終點
for(int l=0;l<=r;l++){//左指針
u=dui[l];
for(int e=head[u];e!=-1;e=edge[e].next){
v=edge[e].to;
if(edge[e].w>0&&lev[v]==-1){//1.能走 2.未分層
lev[v]=lev[u]+1;
r++;
dui[r]=v;//v入隊
if(v==m)return 1;//分層完畢
}
}
}
return 0;//無法分層
}
int dinic(int u,int flow,int m){//u當前點,flow爲下面的點能夠分配多大的流量,m終點
if(u==m)return flow;//終點直接全流入
int res=0,delta;//res實際流量
for(int &e=cur[u];e!=-1;e=edge[e].next){//'&'相當於cur[u]=e;即流滿的邊不會再被掃一次
int v=edge[e].to;
if(edge[e].w>0&&lev[u]<lev[v]){//只能從低層往高層流
delta=dinic(v,min(edge[e].w,flow-res),m);
if(delta>0){//如果增廣
edge[e].w-=delta;//正向邊容量減少
edge[e^1].w+=delta;//反向邊仍量增加(暗示退流)
res+=delta;//擴張流量增加
if(res==flow)break;//可流的都流完了,及時跳出
}
}
}
if(res!=flow)lev[u]=-1;//沒流完,說明以後不能從這個點流出任何流量,那就不需要這個點了
return res;
}
char a[14][14];
int vis[14][14],dis[14][14];
void BFS(int x,int y){
int x1[160],y1[160];
int r=0;
x1[0]=x;y1[0]=y;dis[x][y]=0;
for(int l=0;l<=r;l++){
int t1=x1[l],t2=y1[l];
if(a[t1+1][t2]!='X'&&vis[t1+1][t2]==0){
r++;
x1[r]=t1+1;y1[r]=t2;
vis[t1+1][t2]=1;
dis[t1+1][t2]=min(dis[t1+1][t2],dis[t1][t2]+1);
}
if(a[t1-1][t2]!='X'&&vis[t1-1][t2]==0){
r++;
x1[r]=t1-1;y1[r]=t2;
vis[t1-1][t2]=1;
dis[t1-1][t2]=min(dis[t1-1][t2],dis[t1][t2]+1);
}
if(a[t1][t2+1]!='X'&&vis[t1][t2+1]==0){
r++;
x1[r]=t1;y1[r]=t2+1;
vis[t1][t2+1]=1;
dis[t1][t2+1]=min(dis[t1][t2+1],dis[t1][t2]+1);
}
if(a[t1][t2-1]!='X'&&vis[t1][t2-1]==0){
r++;
x1[r]=t1;y1[r]=t2-1;
vis[t1][t2-1]=1;
dis[t1][t2-1]=min(dis[t1][t2-1],dis[t1][t2]+1);
}
}
return;
}
int id[14][14];
int rdis[14][14][144]={0};
int main(){
int r,c,t;
int sumH=0,sumE=0;
scanf("%d%d%d\n",&r,&c,&t);
for(int i=1;i<=r;i++){
for(int j=1;j<=c+1;j++){
scanf("%c",a[i][j]);
if(a[i][j]=='.'){
sumH++;
id[i][j]=sumH;
}
if(a[i][j]=='E'){
sumE++;
id[i][j]=sumE;
}
}
}
for(int i=1;i<=r;i++){
a[i][0]='X';a[i][c+1]='X';
}
for(int j=1;j<=c;j++){
a[0][j]='X';a[r+1][j]='X';
}
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
if(a[i][j]=='E'){
memset(vis,0,sizeof(vis));
for(int k=1;k<=r;k++){
for(int l=1;l<=c;l++){
dis[k][l]=INF-1;
}
}
BFS(i,j);
for(int k=1;k<=r;k++){
for(int l=1;l<=c;l++){
if(a[k][l]=='.'){
rdis[k][l][id[i][j]]=dis[k][l];
}
}
}
}
}
}
for(int i=1;i<=t+sum+2;i++){
head[i]=-1;
}
for(int i=1;i<=n;i++){
int s,e,c;
scanf("%d%d%d",&s,&e,&c);
add(s,e,c);
add(e,s,0);
}
int ans=0;
while(bfs(m)==1)ans+=dinic(1,INF,m);
printf("%d",ans);
return 0;
}
http://codevs.cn/problem/1993/
草地排水,網絡流dinic板子
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=201;
const int INF=2147483640;
struct{
int next;
int to;
int w;
}edge[2*maxn];
int head[2*maxn],cnt=-1;
void add(int u,int v,int w){//u起點v終點w容量
cnt++;
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt;
}
int lev[maxn],cur[maxn];//lev層數,cur[i]爲以i爲起點的邊的編號
bool bfs(int m){//強制1爲源點,m爲匯點
int dui[m],r=0;//隊列和右指針
for(int i=1;i<=m;i++){//初始化
lev[i]=-1;
cur[i]=head[i];
}
dui[0]=1,lev[1]=0;
int u,v;//u起點v終點
for(int l=0;l<=r;l++){//左指針
u=dui[l];
for(int e=head[u];e!=-1;e=edge[e].next){
v=edge[e].to;
if(edge[e].w>0&&lev[v]==-1){//1.能走 2.未分層
lev[v]=lev[u]+1;
r++;
dui[r]=v;//v入隊
if(v==m)return 1;//分層完畢
}
}
}
return 0;//無法分層
}
int dinic(int u,int flow,int m){//u當前點,flow爲下面的點能夠分配多大的流量,m終點
if(u==m)return flow;//終點直接全流入
int res=0,delta;//res實際流量
for(int &e=cur[u];e!=-1;e=edge[e].next){//'&'相當於cur[u]=e;即流滿的邊不會再被掃一次
int v=edge[e].to;
if(edge[e].w>0&&lev[u]<lev[v]){//只能從低層往高層流
delta=dinic(v,min(edge[e].w,flow-res),m);
if(delta>0){//如果增廣
edge[e].w-=delta;//正向邊容量減少
edge[e^1].w+=delta;//反向邊仍量增加(暗示退流)
res+=delta;//擴張流量增加
if(res==flow)break;//可流的都流完了,及時跳出
}
}
}
if(res!=flow)lev[u]=-1;//沒流完,說明以後不能從這個點流出任何流量,那就不需要這個點了
return res;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
head[i]=-1;
}
for(int i=1;i<=n;i++){
int s,e,c;
scanf("%d%d%d",&s,&e,&c);
add(s,e,c);
add(e,s,0);
}
int ans=0;
while(bfs(m)==1)ans+=dinic(1,INF,m);
printf("%d",ans);
return 0;
}
【題目描述】
給出一張n*n(n<=100)的國際象棋棋盤,其中被刪除了一些點,問可以使用多少1*2的多米諾骨牌進行掩蓋。
【輸入格式】
第一行爲n,m(表示有m個刪除的格子)
第二行到m+1行爲x,y,分別表示刪除格子所在的位置
【輸出格式】
一個數,即最大覆蓋格數
【樣例輸入】
8 0
【樣例輸出】
32
想象真的國際象棋棋盤,黑色的一幫,白色的一幫,黑白相鄰的那麼從黑連向白的,變成二分圖匹配。
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=102;
int n,m,e;
bool vis[maxn][maxn],a[maxn][maxn][maxn][maxn]={0};//u,v
int shu[maxn][maxn][2]={0};//判斷m中點與n中何點連接
bool dfs(int i,int j){
for(int k=-1;k<=1;k++){
for(int l=-1;l<=1;l++){
if(k==l||k+l==0)continue;
if(i+k==0||j+l==0||i+k==n+1||j+l==n+1)continue;
if(a[i][j][i+k][j+l]&&!vis[i+k][j+l]){
vis[i+k][j+l]=1;
if((!shu[i+k][j+l][0]&&!shu[i+k][j+l][1])||dfs(shu[i+k][j+l][0],shu[i+k][j+l][1])){
shu[i+k][j+l][0]=i;
shu[i+k][j+l][1]=j;
return 1;
}
}
}
}
return 0;
}
int main(){
int u,v,ans=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i%2==j%2){
a[i][j][i-1][j]=a[i][j][i+1][j]=a[i][j][i][j-1]=a[i][j][i][j+1]=1;
}
}
}
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
if(x%2==y%2){
a[x][y][x-1][y]=a[x][y][x+1][y]=a[x][y][x][y-1]=a[x][y][x][y+1]=0;
}else{
a[x-1][y][x][y]=a[x+1][y][x][y]=a[x][y-1][x][y]=a[x][y+1][x][y]=0;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
memset(vis,0,sizeof(vis));
if(dfs(i,j))ans++;
}
}
printf("%d",ans);
return 0;
}
codevs1789:最大獲利
http://codevs.cn/problem/1789/
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=55010;
const int INF=2147483640;
struct{
int next;
int to;
int w;
}edge[6666666];//隨便打的不然maxn的平方會爆空間
int head[maxn],cnt=-1;
void add(int u,int v,int w){//u起點v終點w容量
cnt++;
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt;
}
int lev[maxn],cur[maxn];//lev層數,cur[i]爲以i爲起點的邊的編號
bool bfs(int n,int m,int zong){//n爲源點,m爲匯點,zong爲個數
int dui[zong+1],r=0;//隊列和右指針
for(int i=1;i<=zong;i++){//初始化
lev[i]=-1;
cur[i]=head[i];
}
dui[0]=n,lev[n]=0;
int u,v;//u起點v終點
for(int l=0;l<=r;l++){//左指針
u=dui[l];
for(int e=head[u];e!=-1;e=edge[e].next){
v=edge[e].to;
if(edge[e].w>0&&lev[v]==-1){//1.能走 2.未分層
lev[v]=lev[u]+1;
r++;
dui[r]=v;//v入隊
if(v==m)return 1;//分層完畢
}
}
}
return 0;//無法分層
}
int dinic(int u,int flow,int m){//u當前點,flow爲下面的點能夠分配多大的流量,m終點
if(u==m)return flow;//終點直接全流入
int res=0,delta;//res實際流量
for(int &e=cur[u];e!=-1;e=edge[e].next){//'&'相當於cur[u]=e;即流滿的邊不會再被掃一次
int v=edge[e].to;
if(edge[e].w>0&&lev[u]<lev[v]){//只能從低層往高層流
delta=dinic(v,min(edge[e].w,flow-res),m);
if(delta>0){//如果增廣
edge[e].w-=delta;//正向邊容量減少
edge[e^1].w+=delta;//反向邊仍量增加(暗示退流)
res+=delta;//擴張流量增加
if(res==flow)break;//可流的都流完了,及時跳出
}
}
}
if(res!=flow)lev[u]=-1;//沒流完,說明以後不能從這個點流出任何流量,那就不需要這個點了
return res;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n+m+2;i++){
head[i]=-1;
}
for(int i=1;i<=n;i++){
int s;
scanf("%d",&s);
add(i,n+m+2,s);
add(n+m+2,i,0);
}
int sum=0;
for(int j=n+1;j<=n+m;j++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(j,a,INF);add(a,j,0);
add(j,b,INF);add(b,j,0);
add(n+m+1,j,c);add(j,n+m+1,0);
sum+=c;
}
int ans=0;
while(bfs(n+m+1,n+m+2,n+m+2)==1)ans+=dinic(n+m+1,INF,n+m+2);
printf("%d",sum-ans);
return 0;
}
codevs 1163訪問藝術館
http://codevs.cn/problem/1163/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int tree[201][601];
int dis[201][201];
int t;
const int INF=214748364;
int hua[201]={0};
int sum=0;
void read(int fa,int i){
scanf("%d",&dis[fa][i]);
int ha;
scanf("%d",&ha);
if(ha==0){
read(i,i*2);
read(i,i*2+1);
hua[i]=hua[i*2+1]+hua[i*2];
for(int j=0;j<=hua[i];j++){
for(int k=0;k<=j;k++){
int f=0;
if(k!=0)f+=dis[i][i*2]*2;
if(j-k!=0)f+=dis[i][i*2+1]*2;
tree[i][j]=min(tree[i][j],tree[i*2][k]+tree[i*2+1][j-k]+f);
}
}
}else{
hua[i]=ha;
sum+=ha;
for(int j=0;j<=ha;j++){
tree[i][j]=j*5;
}
}
return;
}
int main(){
scanf("%d",&t);
for(int i=0;i<=200;i++){
tree[i][0]=0;
for(int j=1;j<=600;j++){
tree[i][j]=INF;
}
}
read(1,2);
for(int i=sum;i>=0;i--){
if(tree[2][i]+dis[1][2]*2<=t){
printf("%d",i);
return 0;
}
}
return 0;
}
1201: 泥濘的牧場
時間限制: 1 Sec 內存限制: 128 MB
提交: 78 解決: 30
[提交][狀態][討論版]
題目描述
大雨侵襲了奶牛們的牧場.牧場是一個R * C的矩形,其中1≤R,C≤50.大雨將沒有長草的土地弄得泥濘不堪,可是小心的奶牛們不想在喫草的時候弄髒她們的蹄子.
爲了防止她們的蹄子被弄髒,約翰決定在泥濘的牧場裏放置一些木板.每一塊木板的寬度爲1個單位,長度任意.每一個板必須放置在平行於牧場的泥地裏.
約翰想使用最少的木板覆蓋所有的泥地.一個木板可以重疊在另一個木板上,但是不能放在草地上.
輸入
第1行:兩個整數R和C.
第2到R+1行:每行C個字符,其中“*’代表泥地,“.”代表草地.
輸出
最少需要多少木板.
樣例輸入
4 4
..
.*
*.
..*.
樣例輸出
4
提示
樣例說明:
木板的放置方法如下:
1.2.
.333
444.
..2.
木板2和3、4重疊
每個點可以橫着板子來與豎着板子來。
那就橫着豎着點連一條線,然後要求所有線都能夠到
那就是最小點覆蓋了+-+
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1000;
int n,m;
char s[maxn][maxn]={0};
int c[maxn][maxn]={0},d[maxn][maxn]={0};
bool vis[maxn],a[maxn][maxn]={0};//u,v
int shu[maxn]={0};//判斷m中點與n中何點連接
bool dfs(int i,int o){
for(int j=1;j<=o;j++){
if(a[i][j]&&!vis[j]){
vis[j]=1;
if(!shu[j]||dfs(shu[j],o)){
shu[j]=i;
return 1;
}
}
}
return 0;
}
int main(){
int u,v,ans=0;
int x1=0,y1=0;
scanf("%d%d\n",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m+1;j++){
scanf("%c",&s[i][j]);
if(j==m+1)continue;
if(s[i][j]=='*'){
if(j>1&&s[i][j-1]=='*')c[i][j]=c[i][j-1];
else{
x1++;
c[i][j]=x1;
}
if(i>1&&s[i-1][j]=='*')d[i][j]=d[i-1][j];
else{
y1++;
d[i][j]=y1;
}
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i][j]=='*')
a[c[i][j]][d[i][j]]=1;
}
}
int k=x1;
for(int i=1;i<=k;i++){
memset(vis,0,sizeof(vis));
if(dfs(i,y1))ans++;
}
printf("%d",ans);
return 0;
}
自學KMP
然而
https://www.luogu.org/problem/show?pid=3375
雖然是板子題。
但特別不推薦寫。
可能會出現:
1.cincout卡時間
2.gets函數做答案是對的但是就是不給過//深受此毒害的路由器
#include<cstdio>
#include<cstring>
using namespace std;
char s1[1000001];
char s2[1001];
int nxt[1001]={0};
void getnext(int m){//處理nxt數組
//原理:自己匹配自己
int j=0;
for(int i=2;i<=m;i++){
while(j!=0&&s2[j+1]!=s2[i])j=nxt[j];//無法匹配時移動字符串使之能匹配
if(s2[j+1]==s2[i])j++;
nxt[i]=j;//對應匹配的位置(同時也是匹配的長度)
}
return;
}
void KMP(int n,int m){//KMP
int j=0;
for(int i=1;i<=n;i++){
while(j!=0&&s2[j+1]!=s1[i])j=nxt[j];//同上
if(s2[j+1]==s1[i])j++;
if(j==m){//同上
printf("%d\n",i-j+1);
j=nxt[j];//繼續查找
}
}
return;
}
int main(){
scanf("%s%s",s1+1,s2+1);
//雖然可以從0開始讀入字符串
//但是懶
int n=strlen(s1+1),m=strlen(s2+1);
//相應的字符串長度改一下
getnext(m);
KMP(n,m);
for(int i=1;i<=m;i++){
printf("%d ",nxt[i]);
}
return 0;
}
下面兩道是AC自動機模版題
都挺坑的。
十分感謝上面題解的第一位仁兄。
我把他的模版復刻了一遍才過。
另外我才知道用string讀字符串要方便。
並且直接用字符串還會更快(這什麼原理?!)
總之AC自動機這個黑科技我還沒會透。
就這樣吧。
https://www.luogu.org/problem/show?pid=3808
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
struct trie{
int ed;
int a[26];
int fail;
}tree[1000000]={0};
int cnt=0;
inline void insert(string s){
int now=0;
int len=s.length();
for(int i=0;i<len;i++){
int t=s[i]-97;
if(tree[now].a[t]==0){
cnt++;
tree[now].a[t]=cnt;
}
now=tree[now].a[t];
}
tree[now].ed++;
return;
}
void getfail(){
queue<int>q;
tree[0].fail=0;
//以下是對第一層的特殊處理
for(int i=0;i<26;i++){
if(tree[0].a[i]!=0){
tree[tree[0].a[i]].fail=0;
q.push(tree[0].a[i]);
}
}
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<26;i++){
if(tree[u].a[i]!=0){
tree[tree[u].a[i]].fail=tree[tree[u].fail].a[i];
q.push(tree[u].a[i]);
}else{
tree[u].a[i]=tree[tree[u].fail].a[i];
}
}
}
return;
}
int check(string s){
int now=0,ans=0;
int len=s.length();
for(int i=0;i<len;i++){
int t=s[i]-97;
now=tree[now].a[t];
for(int j=now;j&&tree[j].ed!=-1;j=tree[j].fail){
ans+=tree[j].ed;
tree[j].ed=-1;
}
}
return ans;
}
int main(){
int n;
string s;
cin>>n;
for(int i=1;i<=n;i++){
cin>>s;
insert(s);
}
getfail();
cin>>s;
cout<<check(s);
return 0;
}
https://www.luogu.org/problem/show?pid=3796
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
struct trie{
int ed;
int a[26];
int fail;
}tree[100000]={0};
struct remember{
int cont;
int i;
}re[100000]={0};
string s[100000];
bool cmp(remember a,remember b){
if(a.cont!=b.cont)
return a.cont>b.cont;
else
return a.i<b.i;
}
int cnt=0;
inline void insert(string s,int num){
int now=0;
int len=s.length();
for(int i=0;i<len;i++){
int t=s[i]-97;
if(tree[now].a[t]==0){
cnt++;
tree[now].a[t]=cnt;
}
now=tree[now].a[t];
}
tree[now].ed=num;
return;
}
void getfail(){
queue<int>q;
tree[0].fail=0;
//以下是對第一層的特殊處理
for(int i=0;i<26;i++){
if(tree[0].a[i]!=0){
tree[tree[0].a[i]].fail=0;
q.push(tree[0].a[i]);
}
}
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<26;i++){
if(tree[u].a[i]!=0){
tree[tree[u].a[i]].fail=tree[tree[u].fail].a[i];
q.push(tree[u].a[i]);
}else{
tree[u].a[i]=tree[tree[u].fail].a[i];
}
}
}
return;
}
void check(string s){
int now=0;
int len=s.length();
for(int i=0;i<len;i++){
int t=s[i]-97;
now=tree[now].a[t];
for(int j=now;j;j=tree[j].fail){
re[tree[j].ed].cont++;
}
}
return;
}
inline void clean(int i){
memset(tree[i].a,0,sizeof(tree[i].a));
tree[i].fail=0;
tree[i].ed=0;
return;
}
int main(){
int n=1;
while(n!=0){
cin>>n;
if(n==0)break;
for(int i=0;i<=cnt;i++){
clean(i);
}
cnt=0;
for(int i=1;i<=n;i++){
cin>>s[i];
re[i].cont=0;
re[i].i=i;
insert(s[i],i);
}
getfail();
cin>>s[0];
check(s[0]);
sort(re+1,re+n+1,cmp);
cout<<re[1].cont<<endl;
cout<<s[re[1].i]<<endl;
for(int i=2;i<=n;++i){
if(re[i].cont==re[i-1].cont){
cout<<s[re[i].i]<<endl;
}
else break;
}
}
return 0;
}
P3366 【模板】最小生成樹
https://www.luogu.org/problem/show?pid=3366
//kruskal
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
struct edge{
int u;
int v;
int w;
}e[200001];
bool cmp(edge a,edge b){
return a.w<b.w;
}
int fa[5001]={0};
int find(int a){
if(fa[a]!=a)fa[a]=find(fa[a]);
return fa[a];
}
bool unionn(int a,int b){
int k=find(a);
int p=find(b);
if(k!=p){
fa[p]=k;
return 1;
}
return 0;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
}
sort(e+1,e+1+m,cmp);
int cnt=0,sum=0;
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++){
if(unionn(e[i].u,e[i].v)){
cnt++;
sum+=e[i].w;
}
if(cnt==n-1)break;
}
int pan=0;
for(int i=1;i<=n;i++)if(fa[i]==i)pan++;
if(pan==1)printf("%d",sum);
else printf("orz");
return 0;
}
寒假考試題
質數
結果碰到了然後重新寫了一波
發現這種寫法比較好理解
那麼存一下把
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
int a[1001];
int on[1001]={0};
int n,m;
int sfk[1001]={0};
int suan=0;
void gredy(int maxn){
if(maxn>m)return;
for(int i=maxn;i<=m;i++){
int ok=0,mie=0;
for(int j=a[i];j<=n;j++){
if(j%a[i]==0){
if(on[j]==1){
mie++;
}
if(on[j]==0){
ok++;
}
}
}
if(ok>mie){
for(int j=a[i];j<=n;j++){
if(j%a[i]==0){
on[j]=1-on[j];
}
}
}
}
return;
}
void dfs(int i,int maxn){
if(i>maxn){
memset(on,0,sizeof(on));
for(int j=1;j<=maxn;j++){
if(sfk[j]==1){
for(int k=a[j];k<=n;k++){
if(k%a[j]==0){
on[k]=1-on[k];
}
}
}
}
gredy(maxn+1);
int ans=0;
for(int i=1;i<=n;i++){
if(on[i]==1)ans++;
}
if(ans>suan){
suan=ans;
}
}else{
for(int j=1;j>=0;j--){
sfk[i]=j;
dfs(i+1,maxn);
}
}
return;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
suan=0;
memset(sfk,0,sizeof(sfk));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+m+1);
int maxn=min(m,11);
dfs(1,maxn);
printf("%d\n",suan);
}
return 0;
}
記一道題
51nod 1459 迷宮遊戲
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1459
得等我複習dji才能寫了……暴力被卡時了
TLE代碼如下
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=501;
const int INF=2147483630;
int sc[maxn];
struct{
int to;
int next;
int w;
}edge[maxn*2];
int cnt=0,head[maxn]={0};
void add(int u,int v,int w){
cnt++;
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt;
return;
}
bool vis[maxn]={0};
int mint=INF,maxw=0;
void dfs(int u,int ed,int t,int sum){
if(u==ed){
if(mint>t){
mint=t;
maxw=sum;
}else if(mint==t){
if(maxw<sum){
maxw=sum;
}
}
return;
}
if(t>mint)return;
vis[u]=1;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
int w=edge[i].w;
if(vis[v]==0){
dfs(v,ed,t+w,sum+sc[v]);
vis[v]=0;
}
}
return;
}
int main(){
int n,m,st,ed;
scanf("%d%d%d%d",&n,&m,&st,&ed);
for(int i=0;i<n;i++){
scanf("%d",&sc[i]);
}
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
dfs(st,ed,0,sc[st]);
printf("%d %d",mint,maxw);
return 0;
}
hdu 5188
一道需要動腦子的01揹包。
於是做一半就去看題解了……gg。
能力還不夠啊。
空間最初開小了。
然後就直接看題解的空間開多大就開多大了。
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct node{
int t;
int v;
int l;
}a[31];
bool cmp(node b,node c){
if((b.l-b.t)<(c.l-c.t))return 1;
return 0;
}
int f[3000005]={0};//表示時間用量
int main(){
int n;
while(scanf("%d",&n)!=EOF){
memset(f,0,sizeof(f));
int w,ans=0,sum=0,maxn=0;
scanf("%d",&w);
for(int i=1;i<=n;i++){
scanf("%d%d%d",&a[i].t,&a[i].v,&a[i].l);
sum+=a[i].v;//分數總和
ans+=a[i].t;//時間總和
maxn=max(maxn,a[i].l);//最遲交題時間
}
if(w>sum){//分數和不夠要求
printf("zhx is naive!\n");
continue;
}
sort(a+1,a+n+1,cmp);
maxn=max(maxn,ans);//與時間總和再比
for(int i=1;i<=n;i++){
for(int j=maxn;j>=a[i].l;j--){//該題可答時間段
if(j>=a[i].t){//該題是否合法
f[j]=max(f[j],f[j-a[i].t]+a[i].v);
}
}
}
bool ok=0;
for(int i=0;i<=maxn;i++){
if(f[i]>=w){
printf("%d\n",i);
ok=1;
break;
}
}
if(ok==0){
printf("zhx is naive!\n");
}
}
return 0;
}