11.26补坑

来源:互联网 发布:mac与windows共享文件 编辑:程序博客网 时间:2024/06/11 08:51

#include <bits/stdc++.h>using namespace std;#define rep(i,j,k) for(int i=(j);i<=(k);i++)#define pb push_back#define mem(a,k) memset(a,k,sizeof(a))#define mp make_pairtypedef pair<int,int> P;const int N = 1E5 + 7,inf = 0x3f3f3f3f;struct node{    int to,val;};vector<node>g[N];int d[N],n,m,ans[N],vis[N];void bfs1(){    mem(d,-1);    d[n] = 0;    queue<P>que;    que.push(mp(n,0));    while(!que.empty()) {        P u = que.front(); que.pop();        for(int i = 0;i < g[u.first].size();i ++) {            int to = g[u.first][i].to;            if(d[to] == -1) {                d[to] = d[u.first] + 1;                que.push(mp(to,d[to]));            }        }    }    //for(int i = 1;i <= n;i ++) printf("%d ",d[i]);}void bfs2(){    mem(ans,0x3f);    mem(vis,0);    queue<int>que;    que.push(1);    vis[1] = 1;    for(int i = 0;i < d[1];i ++) {        vector<int>tmp;        int res = inf;        while(!que.empty()) {            int u = que.front(); que.pop();            tmp.push_back(u);            for(int i = 0;i < g[u].size();i ++) {                int to = g[u][i].to, val = g[u][i].val;                if(d[to] == d[u]-1) {                    res = min(res, val);                }            }        }        ans[i] = res;        for(int& it:tmp) {            for(auto& u:g[it]) {                int to = u.to, val = u.val;                if(d[to] == d[it]-1 && val == res && !vis[to]) {                    que.push(to);                    vis[to] = 1;                }            }        }    }    printf("%d\n",d[1]);    for(int i = 0;i < d[1];i ++) printf("%d%c",ans[i],i==d[1]-1?'\n':' ');}int main(){    while(scanf("%d%d",&n,&m) == 2) {        rep(i,1,n) g[i].clear();        rep(i,1,m) {            int u, v, val;            scanf("%d%d%d",&u,&v,&val);            g[u].pb({v,val});            g[v].pb({u,val});        }        bfs1();        bfs2();    }    return 0;}

UVA10129 题目链接:https://vjudge.net/contest/200148#problem/D

题意:输入n个单词,是否可以把所有这些单词排成一个序列,使得每个单词的第一个字母和上一个单词的最后一个字母相同,每个单词最多包含1000个小写字母,输入可以由重复。

题解:把字母看做节点,由于只是首位相连,每个单词只要首尾位即可,首位入度+1,末尾出度+1,合并。若有解,必须有欧拉路径。

先并查集看联通,然后判断度的关系即可。

////////////////////////////////////////////////////////////////////

#include <bits/stdc++.h>using namespace std;const int N = 30;char s[1<<10];int in[N], out[N], par[N], vis[N];int find(int x){return x==par[x] ? x : par[x]=find(par[x]);}void unit(int x, int y){    x = find(x), y = find(y);    if(x!=y) par[y] = x;}int main(){    int T;    scanf("%d",&T);    while(T --) {        int n;        for(int i = 0;i < 26;i ++) par[i] = i;        memset(in, 0, sizeof(vis));        memset(out,0,sizeof(out));        scanf("%d",&n);        for(int i = 1;i <= n;i ++) {            scanf("%s",s);            int len = strlen(s);            in[s[0]-'a'] ++;            out[s[len-1]-'a'] ++;            unit(s[0]-'a', s[len-1]-'a');        }        int fg = 0;        for(int i = 0;i < 26;i ++) {            if((in[i]||out[i])&& i == par[i]) fg ++;        }        if(fg != 1) {            puts("The door cannot be opened.");        } else {            int dif = 0;            for(int i = 0;i < 26;i ++) {                if(in[i] != out[i]) dif ++;            }            if(dif != 2 && dif != 0) {                puts("The door cannot be opened.");            } else {                if(dif == 0) {                    puts("Ordering is possible.");                } else {                    vector<int>vec;                    for(int i = 0;i < 26;i ++) {                        if(in[i] != out[i]) {                            vec.push_back(i);                        }                    }                    assert(vec.size() == 2);                    bool flag = 0;                    if(in[vec[0]] == 1 + out[vec[0]] && in[vec[1]] == -1 + out[vec[1]]) flag = 1;                    swap(vec[0], vec[1]);                    if(in[vec[0]] == 1 + out[vec[0]] && in[vec[1]] == -1 + out[vec[1]]) flag = 1;                    if(flag) puts("Ordering is possible.");                    else puts("The door cannot be opened.");                }            }        }    }    return 0;}
UVA1599

感觉这题很好紫书P1599,弱鸡只会2次BFS,感觉最妙的是第2次BFS,对每层BFS,取最优(好几个相同的话,都入队列)。

///////////////////////////////////////////////

UVA11853

附上链接,看了这2个图和讲解终于知道怎么写了,难点在与从上放开始DFS,重点部分代码里标记了。


#include <bits/stdc++.h>using namespace std;const double R = 1000.0;const int N = 1024;int n;pair<pair<int,int>,int>cir[N];#define fi first#define se seconddouble left_,right_;bool vis[N];inline bool ins(int a,int b){    return hypot(fabs(cir[a].fi.fi-cir[b].fi.fi),fabs(cir[a].fi.se-cir[b].fi.se)) < cir[a].se + cir[b].se;}void update(int a){
    //附上链接里图片很好说明这2个更新    if(cir[a].fi.fi - cir[a].se < 0) left_ = min(left_, cir[a].fi.se - sqrt(cir[a].se*cir[a].se-cir[a].fi.fi*cir[a].fi.fi)); .    if(cir[a].fi.fi + cir[a].se > R) right_ = min(right_, cir[a].fi.se - sqrt(cir[a].se*cir[a].se-(R-cir[a].fi.fi)*(R-cir[a].fi.fi)));}bool dfs(int u){    if(vis[u]) return false;    vis[u] = 1;    if(cir[u].fi.se < cir[u].se) return true; //某次这个圆与下方x轴接触了,则一定封闭了图形,无解    for(int i = 0;i < n;i ++) {        if(ins(u,i) && dfs(i)) return true;    }    update(u);    return false;}int main(){    std::ios::sync_with_stdio(false), cin.tie(0);    while(cin >> n) {        memset(vis, 0, sizeof(vis));        left_ = right_ = 1000;        for(int i = 0;i < n;i ++) cin >> cir[i].fi.fi >> cir[i].fi.se >> cir[i].se;        bool ok = true;        for(int i = 0;i < n;i ++) {            if(cir[i].fi.se+cir[i].se >= R && dfs(i)) { //说明与上方有接触,有可能形成封闭的图形,dfs才有意义。                ok = false; break;            }        }        if(ok) {            cout << fixed << setprecision(2) << "0.00 " << left_ << " 1000.00 " << right_ << '\n';        } else {            cout << "IMPOSSIBLE\n";        }    }    return 0;}



/////////////////////////////////////////////////////




原创粉丝点击