A—地鐵 B—Barareh on Fire C—Apache is late again

Description

 Bobo 居住在大城市 ICPCCamp。

ICPCCamp 有 n 個地鐵站,用 1,2,…,n 編號。 m 段雙向的地鐵線路連接 n 個地鐵站,其中第 i 段地鐵屬於 ci 號線,位於站 ai,bi 之間,往返均需要花費 ti 分鐘(即從 ai 到 bi 需要 ti 分鐘,從 bi 到 ai 也需要 ti 分鐘)。
衆所周知,換乘線路很麻煩。如果乘坐第 i 段地鐵來到地鐵站 s,又乘坐第 j 段地鐵離開地鐵站 s,那麼需要額外花費 |ci-cj | 分鐘。注意,換乘只能在地鐵站內進行。
Bobo 想知道從地鐵站 1 到地鐵站 n 所需要花費的最小時間。

Input

輸入包含不超過 20 組數據。
每組數據的第一行包含兩個整數 n,m (2≤n≤105,1≤m≤105).
接下來 m 行的第 i 行包含四個整數 ai,bi,ci,ti (1≤ai,bi,ci≤n,1≤ti≤109).
保證存在從地鐵站 1 到 n 的地鐵線路(不一定直達)。

Output

對於每組數據,輸出一個整數表示要求的值。

Sample Input

3 3
1 2 1 1
2 3 2 1
1 3 1 1
3 3
1 2 1 1
2 3 2 1
1 3 1 10
3 2
1 2 1 1
2 3 1 1

Sample Output

1
3
2

思路:當點作爲突破口會出現錯誤時考慮從邊作爲突破口的遍歷

#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  
#include<vector>  
#include<queue>  
using namespace std;  
#define INF  999999999999999  
#define MAX (10*10*10*10*10+10)  
struct edge  
{  
    long long  from,to,ci,w,id;  
};  
struct node  
{  
   long long int x,sum;  
   int father;  
    friend bool operator < (node n1,node n2)  
    {  
        return n1.sum>n2.sum; //<爲從大到小,>大於從小到大;  
    }  
};  
long long int tot;  
vector<int>G[MAX];  
vector<edge>edges;  
long long int ans;  
long long int n,m;  
int vis[MAX*2];  
void addedge(long long int x,long long int y,long long int ci,long long int w)  
{  
    edge v={x,y,ci,w,tot++};  
    edges.push_back(v);  
    G[x].push_back(edges.size()-1);  
}  
void bfs()  
{  
   memset(vis,0,sizeof(vis));  
   node a={1,0,-1};  
   priority_queue<node>q;  
   q.push(a);  
   while(!q.empty())  
   {  
       a=q.top();  
       q.pop();  
       if(a.x==n)  
       {  
         ans=a.sum;  
           return ;  
       }  
       if(a.father!=-1&&vis[a.father]) continue;  
       vis[a.father]=1;  
       for(int i=0;i<G[a.x].size();i++)  
       {  
            node b=a;  
            edge v=edges[G[a.x][i]];  
            b.x=v.to;  
            b.father=G[a.x][i];  
            b.sum+=v.w;  
            if(a.father>=0)  
            {  
                b.sum+=abs(edges[a.father].ci-v.ci);  
            }  
            q.push(b);  
  
       }  
   }  
  
}  
int main()  
{  
    while(scanf("%lld %lld",&n,&m)!=EOF)  
    {  
        for(int i=1;i<=n;i++)  
        {  
            G[i].clear();  
        }  
        edges.clear();  
        tot=1;  
        for(int i=1;i<=m;i++)  
        {  long long int x,y,ci,w;  
            scanf("%lld %lld %lld %lld",&x,&y,&ci,&w);  
            addedge(x,y,ci,w);  
            addedge(y,x,ci,w);  
        }  
       ans=INF;  
       bfs();  
       printf("%lld\n",ans);  
    }  
}  
/**********************************************************************
	Problem: 1808
	User: jk1601zr
	Language: C++
	Result: AC
	Time:1772 ms
	Memory:21244 kb
**********************************************************************/

B——雙向bfs,詳見https://blog.csdn.net/Abandoninged/article/details/79845959

C——

Description

Apache is a student of CSU. There is a math class every Sunday morning, but he is a very hard man who learns late every night. Unfortunate, he was late for maths on Monday. Last week the math teacher gave a question to let him answer as a punishment, but he was easily resolved. So the math teacher prepared a problem for him to solve. Although Apache is very smart, but also was stumped. So he wants to ask you to solve the problem. Questions are as follows: You can find a m made (1 + sqrt (2)) ^ n can be decomposed into sqrt (m) + sqrt (m-1), if you can output m% 100,000,007 otherwise output No.

Input

There are multiply cases. Each case is a line of n. (|n| <= 10 ^ 18)

Output

Line, if there is no such m output No, otherwise output m% 100,000,007.

Sample Input

2

Sample Output

9

本題參考隊長的思路,利用數學和快速冪來做

題目大意:給你一個n,讓你計算能否找到一個m使得 
(1+2)n=m+m1(1+2)n=m+m−1 
解題思路:先寫出前幾項 
(1+2)1=2+1=12+1+12(1+2)1=2+1=12+1+12 
(1+2)2=9+8=32+321(1+2)2=9+8=32+32−1 
(1+2)3=50+49=72+1+72(1+2)3=50+49=72+1+72 
(1+2)4=289+288=172+1721(1+2)4=289+288=172+172−1 
(1+2)5=1682+1681=412+1+412(1+2)5=1682+1681=412+1+412 
 
設數列: 
a1=1,a2=3,a3=7,a4=17,a5=41,a1=1,a2=3,a3=7,a4=17,a5=41,⋯ 
an=2an1+an2an=2∗an−1+an−2 
所以當n<0時,輸出”No”; 
當n>0時: 
若n爲奇數,m=(an)2+1m=(an)2+1 
若n爲偶數,m=(an)2m=(an)2 
[anan1]=[2110][an1an2]=[2110]n2[a2a1][anan−1]=[2110][an−1an−2]=[2110]n−2[a2a1] 
用矩陣快速冪加速 

#include <iostream>
#include <string.h>
#include <set>
using namespace std;
typedef long long LL;
const int MOD=1e8+7;

struct matrix
{
    LL v[2][2];
    matrix(){memset(v,0,sizeof(v));}
    matrix operator * (const matrix &m)
    {
        matrix c;
        for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
                for(int k=0;k<2;k++)
                    c.v[i][j]+=(v[i][k]*m.v[k][j])%MOD;
        return c;
    }
};

matrix M,E,ans;

void Init()
{
    for(int i=0;i<2;i++)
        E.v[i][i]=1;
    M.v[0][0]=2;M.v[0][1]=1;
    M.v[1][0]=1;M.v[1][1]=0;
}

matrix pow(matrix p,LL k)
{
    matrix tmp=E;
    while(k)
    {
        if(k&1)
        {
            tmp=tmp*p;
            k--;
        }
        k>>=1;
        p=p*p;
    }
    return tmp;
}

int main()
{
    LL n;
    Init();
    while(cin>>n)
    {
        if(n<0) cout<<"No"<<endl;
        else if(n==0) cout<<"1"<<endl;
        else if(n==1) cout<<"2"<<endl;
        else if(n==2) cout<<"9"<<endl;
        else
        {
            ans=pow(M,n-2);
            LL an=(ans.v[0][0]*3+ans.v[0][1]*1)%MOD;
            if(n&1) cout<<((an*an)%MOD+1)%MOD<<endl;
            else cout<<(an*an)%MOD<<endl;
        }
    }
    return 0;
}

/**********************************************************************
	Problem: 1895
	User: jk1601zr
	Language: C++
	Result: AC
	Time:4 ms
	Memory:2024 kb
**********************************************************************/



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章